我已经开发了一个随机字符串生成器,但它的行为并不像我所希望的那样。我的目标是能够运行两次,并生成两个不同的四字符随机字符串。但是,它只生成一个四个字符的随机字符串两次。

下面是代码和输出示例:

private string RandomString(int size)
{
    StringBuilder builder = new StringBuilder();
    Random random = new Random();
    char ch;
    for (int i = 0; i < size; i++)
    {
        ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));                 
        builder.Append(ch);
    }

    return builder.ToString();
}

// get 1st random string 
string Rand1 = RandomString(4);

// get 2nd random string 
string Rand2 = RandomString(4);

// create full rand string
string docNum = Rand1 + "-" + Rand2;

...输出如下:UNTE-UNTE ...但它应该看起来像这个UNTE-FWNU

如何确保两个明显随机的字符串?


当前回答

另一个样本(在vs2013中测试):

    Random R = new Random();
    public static string GetRandomString(int Length)
    {
        char[] ArrRandomChar = new char[Length];
        for (int i = 0; i < Length; i++)
            ArrRandomChar[i] = (char)('a' + R.Next(0, 26));
        return new string(ArrRandomChar);
    }

    string D = GetRandomString(12);

我自己实现的。

其他回答

在方法中实例化Random对象。

Random对象的种子来自系统时钟,这意味着如果您快速连续多次调用方法,它每次都将使用相同的种子,这意味着它将生成相同的随机数序列,这意味着您将得到相同的字符串。

为了解决这个问题,把你的Random实例移到方法本身之外(当你在做的时候,你可以摆脱对Convert和Floor和NextDouble的疯狂调用序列):

private readonly Random _rng = new Random();
private const string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

private string RandomString(int size)
{
    char[] buffer = new char[size];

    for (int i = 0; i < size; i++)
    {
        buffer[i] = _chars[_rng.Next(_chars.Length)];
    }
    return new string(buffer);
}

实际上,一个好的解决方案是为随机数生成器提供一个线程安全且不使用锁的静态方法。

这样,同时访问web应用程序的多个用户就不会得到相同的随机字符串。

这里有3个例子: http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx

我会用最后一个:

public static class RandomGen3
{
    private static RNGCryptoServiceProvider _global = 
        new RNGCryptoServiceProvider();
    [ThreadStatic]
    private static Random _local;

    public static int Next()
    {
        Random inst = _local;
        if (inst == null)
        {
            byte[] buffer = new byte[4];
            _global.GetBytes(buffer);
            _local = inst = new Random(
                BitConverter.ToInt32(buffer, 0));
        }
        return inst.Next();
    }
}

然后就可以适当消去了

Random random = new Random();

只需调用RandomGen3.Next(),而您的方法可以保持静态。

我想也许这也是可以接受的和简单的。

Guid.NewGuid().ToString() 

这个解决方案是Random类的扩展。

使用

class Program
{
    private static Random random = new Random(); 

    static void Main(string[] args)
    {
        random.NextString(10); // "cH*%I\fUWH0"
        random.NextString(10); // "Cw&N%27+EM"
        random.NextString(10); // "0LZ}nEJ}_-"
        random.NextString();   // "kFmeget80LZ}nEJ}_-"
    }
}

实现

public static class RandomEx
{
    /// <summary>
    /// Generates random string of printable ASCII symbols of a given length
    /// </summary>
    /// <param name="r">instance of the Random class</param>
    /// <param name="length">length of a random string</param>
    /// <returns>Random string of a given length</returns>
    public static string NextString(this Random r, int length)
    {
        var data = new byte[length];
        for (int i = 0; i < data.Length; i++)
        {
            // All ASCII symbols: printable and non-printable
            // data[i] = (byte)r.Next(0, 128);
            // Only printable ASCII
            data[i] = (byte)r.Next(32, 127);
        }
        var encoding = new ASCIIEncoding();
        return encoding.GetString(data);
    }

    /// <summary>
    /// Generates random string of printable ASCII symbols
    /// with random length of 10 to 20 chars
    /// </summary>
    /// <param name="r">instance of the Random class</param>
    /// <returns>Random string of a random length between 10 and 20 chars</returns>
    public static string NextString(this Random r)
    {
        int length  = r.Next(10, 21);
        return NextString(r, length);
    }
}

字符串生成器的另一个版本。简单,没有花哨的数学和神奇的数字。而是用一些神奇的字符串来指定允许的字符。

更新: 我将generator设置为静态的,因此当多次调用时,它将不会返回相同的字符串。然而,此代码不是线程安全的,并且绝对不是加密安全的。

对于密码生成,应该使用System.Security.Cryptography.RNGCryptoServiceProvider。

private Random _random = new Random(Environment.TickCount);

public string RandomString(int length)
{
    string chars = "0123456789abcdefghijklmnopqrstuvwxyz";
    StringBuilder builder = new StringBuilder(length);

    for (int i = 0; i < length; ++i)
        builder.Append(chars[_random.Next(chars.Length)]);

    return builder.ToString();
}