C# 如何在C类的构造函数中生成随机数#

C# 如何在C类的构造函数中生成随机数#,c#,methods,random,constructor,C#,Methods,Random,Constructor,我知道在C#中调用类的构造函数中的方法不是一个好的做法,但我坚持了一些奇怪的观点。我的问题是,当我创建类的对象时,我需要在对象中指定一个带有随机数的字段 比如说 class RandomNumberHandler { private int randomNumber; public RandomNumberHandler() { this.randomNumber = GenerateRandomNumber();

我知道在C#中调用类的构造函数中的方法不是一个好的做法,但我坚持了一些奇怪的观点。我的问题是,当我创建类的对象时,我需要在对象中指定一个带有随机数的字段

比如说

class RandomNumberHandler
    {
        private int randomNumber;
        public RandomNumberHandler()
        {
            this.randomNumber = GenerateRandomNumber();
        }

        private int GenerateRandomNumber()
        {
            return (new Random()).Next(3000) + 1000;
        }
    }

就我而言,我需要一个四位数的号码。我曾想过在创建对象的类中生成随机数,并将其作为参数传递给构造函数,但在另一个类中生成随机数似乎也不是一个好主意,因为我试图实现类的强内聚。我这样做是为了在我的大学里学习“高质量代码”课程,我正在寻找最好的方法。欢迎提出任何方法:)

首先:在构造函数中调用非虚方法没有问题。你在哪里读到的?(注意:调用虚拟方法可能是一个问题;这不是一个自动的否定,但您需要非常仔细地观察您正在做什么)

另一方面,每次调用
GenerateRandomNumber
时生成一个新的
Random
实例似乎是浪费。您可以将
Random
实例提取到字段中,以修复以下问题:

class RandomNumberHandler
{
    private readonly Random random = new Random();
    private int randomNumber;

    public RandomNumberHandler()
    {
        this.randomNumber = GenerateRandomNumber();
    }

    private int GenerateRandomNumber()
    {
        return this.random.Next(3000) + 1000;
    }
}
但这又提出了另一个问题:如果在每个实例的生命周期中(在构造函数中)只调用一次
GenerateRandomNumber
,那么为每个对象创建一个新的
Random
是没有意义的。因此,下一个逻辑步骤是使
随机
成为
静态
。这意味着
GenerateRandomNumber
也可以变成
静态的
(事实上,它必须):


首先:在构造函数中调用非虚方法没有什么错。你在哪里读到的?(注意:调用虚拟方法可能是一个问题;这不是一个自动的否定,但您需要非常仔细地观察您正在做什么)

另一方面,每次调用
GenerateRandomNumber
时生成一个新的
Random
实例似乎是浪费。您可以将
Random
实例提取到字段中,以修复以下问题:

class RandomNumberHandler
{
    private readonly Random random = new Random();
    private int randomNumber;

    public RandomNumberHandler()
    {
        this.randomNumber = GenerateRandomNumber();
    }

    private int GenerateRandomNumber()
    {
        return this.random.Next(3000) + 1000;
    }
}
但这又提出了另一个问题:如果在每个实例的生命周期中(在构造函数中)只调用一次
GenerateRandomNumber
,那么为每个对象创建一个新的
Random
是没有意义的。因此,下一个逻辑步骤是使
随机
成为
静态
。这意味着
GenerateRandomNumber
也可以变成
静态的
(事实上,它必须):

简短回答:您应该在所有
Next()调用中使用相同的随机实例。


简短回答:您应该在所有
Next()
调用中使用相同的随机实例。

仅将随机类包装在另一个名为RandomHandler的类中,我看不到任何内聚。我个人认为这很尴尬。如果您需要一个全新的完全随机数,那么只需调用random().Next(3000)或类似于您所说的构造函数内部的任何内容。

仅将random类包装在另一个名为RandomHandler的类中,我看不到任何内聚。我个人认为这很尴尬。如果您需要一个全新的完全随机数,那么只需调用random().Next(3000)或您所说的构造函数内部的任何内容。

此代码可以正常工作-除非如果您快速连续调用它,您可能会得到“相同”的随机数

当然,您可以通过使用静态随机数(如果使用多个线程,则带有线程安全锁)轻松解决此问题,例如:

class RandomNumberHandler
{
    private static Random random = new Random();
    private static object syncObj = new object();

    private int randomNumber;
    public RandomNumberHandler()
    {
        this.randomNumber = GenerateRandomNumber();
    }

    private static int GenerateRandomNumber()
    {
        lock(syncObj)
            return random.Next(3000) + 1000;
    }
}

这段代码可以正常工作——只是如果你连续快速调用它,可能会得到“相同”的随机数

当然,您可以通过使用静态随机数(如果使用多个线程,则带有线程安全锁)轻松解决此问题,例如:

class RandomNumberHandler
{
    private static Random random = new Random();
    private static object syncObj = new object();

    private int randomNumber;
    public RandomNumberHandler()
    {
        this.randomNumber = GenerateRandomNumber();
    }

    private static int GenerateRandomNumber()
    {
        lock(syncObj)
            return random.Next(3000) + 1000;
    }
}

如果将
Random
实例提升为静态字段,并使
GenerateRandomNumber
静态,则可以在
randomname
字段的声明中调用它:

class RandomNumberHandler {
  private static Random random = new Random();
  private int randomNumber = GenerateRandomNumber();

  private static int GenerateRandomNumber() {
    return random.Next(3000) + 1000;
  }
}
或者更简单(可读性较差):

尽管看起来不像是在构造函数中调用方法,但如果查看生成的CIL,您会发现您是


另外,如果您关心线程安全,请看一看。

如果您将
随机
实例提升为静态字段,并使
GeneratorAndomNumber
静态,则可以在
随机数
字段的声明中调用它:

class RandomNumberHandler {
  private static Random random = new Random();
  private int randomNumber = GenerateRandomNumber();

  private static int GenerateRandomNumber() {
    return random.Next(3000) + 1000;
  }
}
或者更简单(可读性较差):

尽管看起来不像是在构造函数中调用方法,但如果查看生成的CIL,您会发现您是


此外,如果您关心线程安全,请查看此信息。

谁知道。。。这些老师总是要把他们的观点强加给学生。我总是按照等级的流程来做。不过在构造函数中调用虚拟方法有一些考虑。可能他对虚拟方法感到困惑。@Kirk,@Eric:当然。但关键是让OP用他自己的话来表达,这样他就可以提高自己的理解力。@Jon,也许吧。但是这句话(黑体字)让我觉得“在构造函数中调用方法没有错”是错误的,或者说是不完整的。谁知道呢。。。这些老师总是要把他们的观点强加给学生。我总是按照等级的流程来做。不过在构造函数中调用虚拟方法有一些考虑。可能他对虚拟方法感到困惑。@Kirk,@Eric:当然。但关键是让OP用他自己的话来表达,这样他就可以提高自己的理解力。@Jon,也许吧。但这句话(粗体字)让我觉得“在构造函数中调用方法没有错”,或者说是错的