c# - 仅在设置断点时创建 Unique Key,否则复制 key

标签 c#

所以,我确信对此有一个简单的解释,但我现在才使用 C# 几个月,所以我还有很多东西要学。

我只是在开发一个生成一组唯一 key 的小应用程序,只是一些基本技能构建的东西。

我遇到了这个问题,如果我在 keyList.Add(sb.ToString()); 处设置一个断点,然后在所有迭代中按 F5,我会得到一个键列表,并且所有键都有唯一值,但如果我删除断点并运行解决方案,它只会重复相同的键。

有人可以解释为什么会这样吗?它与 Random() 或我放置的 StreamWriter 有什么关系吗?

public class KeyCreator
{
    public static void alphaList()
    {
        string lowerAlpha = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
        string upperAlpha = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z";
        SortedList<string, string> alphaList = new SortedList<string, string>();
        string[] splitListLower = lowerAlpha.Split(',');
        string[] splitListUpper = upperAlpha.Split(',');
        for (int i = 0; i < splitListLower.Length; i++)
        {
            alphaList.Add(splitListLower[i], splitListUpper[i]);
        }
        numberGen(alphaList);
    }

    public static void numberGen(SortedList<string, string> alphaList)
    {
        List<string> keyList = new List<string>();
        for (int b = 0; b < 20; b++)
        {
            int max = alphaList.Count;
            StringBuilder sb = new StringBuilder();
            Random rnd = new Random();
            for (int i = 0; i < 4; i++)
            {
                int upperLower = rnd.Next(0, 10);
                if (upperLower < 5)
                {
                    for (int a = 0; a < 4; a++)
                    {
                        int lowerUpper = rnd.Next(0, 10);
                        if (lowerUpper < 4)
                        {
                            int index = rnd.Next(0, max);
                            sb.Append(alphaList.Keys[index]);
                        }
                        else if (lowerUpper > 3 && lowerUpper < 7)
                        {
                            int index = rnd.Next(0, max);
                            sb.Append(alphaList.Values[index]);
                        }
                        else if (lowerUpper > 6)
                        {
                            int rand = rnd.Next(0, 9);
                            sb.Append(rand);
                        }
                    }
                }
                else if (upperLower > 4)
                {
                    for (int a = 0; a < 4; a++)
                    {
                        int lowerUpper = rnd.Next(0, 10);
                        if (lowerUpper < 4)
                        {
                            int index = rnd.Next(0, max);
                            sb.Append(alphaList.Keys[index]);
                        }
                        else if (lowerUpper > 3 && lowerUpper < 7)
                        {
                            int index = rnd.Next(0, max);
                            sb.Append(alphaList.Values[index]);
                        }
                        else if (lowerUpper > 6)
                        {
                            int rand = rnd.Next(0, 9);
                            sb.Append(rand);
                        }
                    }
                }
                if (i < 3)
                {
                    sb.Append("-");
                }
            }
            keyList.Add(sb.ToString());
        }
        using (StreamWriter writer = new StreamWriter(@"C:\temp\keys.txt"))
        {
            foreach (string key in keyList)
            {
                writer.WriteLine(key);
            }
        }
    }
}

最佳答案

问题是这样的:

public static void numberGen(SortedList<string, string> alphaList)
{
    List<string> keyList = new List<string>();
    for (int b = 0; b < 20; b++)
    {
        int max = alphaList.Count;
        StringBuilder sb = new StringBuilder();
        Random rnd = new Random();   //<-- This line is the problem

Random 默认以当前日期/时间作为种子。由于 DateTime 的准确性并不是那么好,您将一遍又一遍地创建相同的随机数。当您中断调试器时,它会起作用,因为您暂停了足够长的时间,以便 DateTime 发生足够的变化,从而为 Random 创建一个新种子。

解决方案是这样做:

[ThreadStatic]
static Random rnd = new Random();
public static void numberGen(SortedList<string, string> alphaList)
{
    //This if is required because it can be null on subsequent threads.
    if (rnd == null) rnd = new Random();
    List<string> keyList = new List<string>();
    for (int b = 0; b < 20; b++)
    {
        int max = alphaList.Count;
        StringBuilder sb = new StringBuilder();

将创建移到循环外并使用相同的实例。

此外,正如 Scott Chamberlain 在评论中指出的那样,Random 不是线程安全的,静态方法应该是,所以我添加了 [ThreadStatic] attribute以避免需要在每个 Next 调用周围lock。不这样做并从多个线程调用它可能会导致 Random 状态被破坏并返回全零。

关于c# - 仅在设置断点时创建 Unique Key,否则复制 key,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33618241/

相关文章:

c# - 使用现有对象插入新对象

javascript - 如果参数不在 AJAX 调用期间,则包含 NULL 条目

c# - WCF 客户端在外部解决方案时不工作

c# - 是否可以在本地主机开发期间选择 Azure 服务配置?例如。云?

c# - 一个图像和一些文本到 ListBox

c# - 如何将富文本呈现为图像?

c# - 在 Unity C# 中将对象缓慢移动到新位置

c# - 具有不同属性的对象的多个值的 XML 到 Linq

c# - 为什么 ajax 在必要时返回值?

c# - FileInfo.GetFiles() 和特殊字符(重音符号)