.NET:Random.Random在静态方法中的运行方式不同

时间:2010-04-29 07:57:38

标签: .net static random

我在以下代码中遇到困难,该代码位于非静态类的静态方法内。

int iRand;
int rand;

rand = new Random((int)DateTime.Now.Ticks);
iRand = rand.Next(50000);

iRand编号以及其他一些值正通过OLEDB插入Access MDB表的新行。 iRand编号被插入到作为主键一部分的字段中,即使iRand编号应该是随机的,插入尝试也会抛出以下异常:

System.Data.OleDb.OleDbException: The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship.  Change the data in the field or fields that contain duplicate data, remove the index, or redefine the index to permit duplicate entries and try again.

由于某种原因,该方法是静态的,是否会使iRand数保持不变?

5 个答案:

答案 0 :(得分:5)

您不应该使用随机数作为主键!首先,是的,在你的情况下,有可能发生碰撞,n / 50000,其中n是先前创建的数字的数量。 (谢谢,Guffa) 其次,为什么不使用顺序值?即首先从1,2,3等开始。没有碰撞,保证唯一。

另一方面,我遇到了随机数在一个周期中被“卡住”的问题,这是因为Random不是线程安全的。这就是我处理它的方式:C# Random Number Generator getting stuck in a cycle

另外,为什么不添加一些日志代码,以便检查输出的随机数,并检查用户数据库中已有多少数据? (虽然我很确定你已经这样做了)

答案 1 :(得分:3)

不,使用静态方法不会有任何区别。但是,如果您在很短的时间内重复调用您的方法,您最终将创建相同的种子。这反过来意味着你将获得从它产生的相同值。顺便说一句,无参数Random构造函数已经从当前日期/时间初始化自己,所以你明确使用它是多余的。

每个线程应该使用Random的单个实例(遗憾的是Random不是线程安全的。)

您可能想要阅读我的blog post以及评论。 (在某些时候我会把它重写为另一篇文章,但这就是我现在所拥有的。)

答案 2 :(得分:1)

原因是您正在创建使用相同起始值播种的Random个对象。当您在时间上创建它们时,DateTime.Now.Ticks值没有时间更改。

创建一个Random对象,用于您要在类中创建的所有随机数。您可以将对象作为参数发送到静态方法中。

请注意,您有时会遇到冲突,随机性并不能保证唯一性。

答案 3 :(得分:1)

除非您绝对确定密钥的其他成员足以定义密钥,否则您不应该使用随机数作为复合主键的一部分 - 此错误表明,在这种情况下,它们不是

说实话,我无法想象为什么你会想要一个随机的PK,但是嘿 - 这是你的表演......

我总是为我生成主键 - 即使在不太好的Oracle中,我使用Sequences来生成它们。

就随机数生成而言,请参阅Guffa的答案。

答案 4 :(得分:0)

扩展Jon的答案,你的课程结构应如此:

static class MyClass
{

    static int iRand = new Random(); // default seed is based on ticks
    static int rand; 

    static void MyMethod()
    {
        rand= rand.Next(50000); 
    }
}