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

发布于 2024-10-26 10:06:59 字数 572 浏览 3 评论 0原文

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

例如

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

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

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

I know that it is not a good practice to call a method in the constructor of a class in C# but I stuck on something strange. My problem is that when I create an object of my class I need to assign a field in my object with a random number.

for instance

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

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

In my case I need a four digit number. I thought of generating the random number in the class where I am creating the object and passing it as a parameter to the constructor but generating a random number in the other class does not seem a very good idea either because I am trying to achieve strong cohesion for my classes. I am doing this for a "High quality code" course in my university and I am looking for the best approach. Any ideas how to do this are welcome :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

二智少女猫性小仙女 2024-11-02 10:07:00

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

顺便说一句,每次调用 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 也可以变成 static (事实上,它必须如此):

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

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

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

First off: there is nothing wrong with calling non-virtual methods in the constructor. Where did you read that there was? (Note: calling virtual methods can be a problem; it is not an automatic no-no, but you need to watch what you are doing very carefully).

As an aside, it seems wasteful to generate a new Random instance every time GenerateRandomNumber is called. You can extract the Random instance to a field to fix that:

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;
    }
}

But this raises another question: if GenerateRandomNumber is only called once in each instance's lifetime (in the constructor), then it doesn't make sense to create a new Random for each object. So the next logical step is to make random be static. This means that GenerateRandomNumber can also become static (and indeed, it has to):

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

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

    private static int GenerateRandomNumber()
    {
        return Random.Next(3000) + 1000;
    }
}
转角预定愛 2024-11-02 10:07:00

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

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

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;
    }
}

This code will work okay - except that you'll likely get the "same" random number if you call it in quick succession.

You could, of course, easily work around that by using a static random number (with a lock for thread safety if you're using multiple threads), such as:

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;
    }
}
心在旅行 2024-11-02 10:07:00

随机数生成器仅生成一个随机数

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

Random number generator only generating one random number

Short answer: You should use same Random instance across all Next() calls.

半寸时光 2024-11-02 10:07:00

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

I don't see any cohesion there by just wrapping the Random class inside of another class named RandomHandler. Personally, I think thats awkward. If you need a brand new completely random number then just call Random().Next(3000) or whatever inside of the constructor like you said.

美煞众生 2024-11-02 10:07:00

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

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

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

或者更简单(可读性较差):

class RandomNumberHandler {
  private static Random random = new Random();
  private int randomNumber = random.Next(3000) + 1000;
}

虽然看起来您不像在构造函数中调用方法,但如果您查看生成的 CIL,您会发现确实如此。

另外,如果您关心线程安全,请查看此

If you lift the Random instance as a static field and make the GenerateRandomNumber static, you can call it in the declaration of the randomNumber field:

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

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

Or more simply (and less readable):

class RandomNumberHandler {
  private static Random random = new Random();
  private int randomNumber = random.Next(3000) + 1000;
}

Although it doesn't look like you're calling a method in a constructor, if you look at the generated CIL, you'll find out that you are.

Also, if you care about thread-safety, take a look at this article.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文