生成随机长度的GUID

时间:2012-01-23 16:06:53

标签: c#

我需要为自动化测试生成随机字符串。我使用以下中文自定义类来完成它。

public class UniqueIdGenerator
  {
    static public string GenerateUniqueId(int idLength)    // generates uniqueID for all fields (0-175 characters)
    {
      string uniqueID = "";
      string initialID = Guid.NewGuid().ToString().Remove(35);

      if (idLength <= 35)
      {
        uniqueID = Guid.NewGuid().ToString().Remove(idLength);
      }
      if (idLength > 35 & idLength <= 70)
      {
        uniqueID = initialID + Guid.NewGuid().ToString().Remove(idLength - 35);
      }
      if (idLength > 70 & idLength <= 105)
      {
        uniqueID = initialID + initialID + Guid.NewGuid().ToString().Remove(idLength - 70);
      }
      if (idLength > 105 & idLength <= 140)
      {
        uniqueID = initialID + initialID + initialID + Guid.NewGuid().ToString().Remove(idLength - 105);
      }
      if (idLength > 140 & idLength <= 175)
      {
        uniqueID = initialID + initialID + initialID + initialID + Guid.NewGuid().ToString().Remove(idLength - 140);
      }

      return uniqueID;
    }

如何简化它以用于任何自然数?

4 个答案:

答案 0 :(得分:23)

这是一个非常糟糕的主意,你不应该这样做。

首先,你说你需要随机字符串,但 guids保证是唯一的,而不是随机的。 Guids 可以成为随机生成,或者可以基于当前时间生成它们,或者可以通过将一系列guid分配给特定机器然后顺序生成它们来生成它们。您可以通过多种方式生成唯一标识符,其中只有一些是随机的。 Guids不保证随机,所以如果你需要随机性,你使用的是错误的工具。

第二,你不能只是从一个指导中取出部件,并期望它仍然是独一无二的,不仅仅是你可以找到“飞行”的飞机部分并期望它在没有其他部件的情况下飞行飞机附在它上面。

如果您需要全球唯一标识符,请创建一个guid。它可能不是随机的,但它将是独一无二的。它不再需要,所以不要添加任何东西。它不能短,否则不再保证是唯一的

如果您需要随机字符串,则根据需要获取随机源 - 伪随机或加密强度 - 并从您选择的字母表中生成随机字符,并将它们串起来一起。您可以通过对其进行“生日问题”碰撞分析来预测其独特的可能性。一个不精确但足够接近的计算是:取字母表中可能的字符数。将其提高到弦长度的一半。这就是在您可能已经生成至少一个字符串两次之前必须生成的字符串数。

例如,如果您的字母为0123456789ABCDEF,那么这是16个字符。如果字符串长度为12个字母,则计算16 6 。这大概是一千六百万,所以你很可能在最初的1600万个字符串中产生两次相同的字符串。

答案 1 :(得分:6)

如果你想要一个任意长度的随机字符串是十六进制字符,你可以使用:

    public static string GetRandomString(int length)
    {
        var rng = new RNGCryptoServiceProvider();
        var padded = (int)Math.Ceiling(length / 2.0m);
        var bytes = new byte[padded];
        rng.GetBytes(bytes);
        return bytes.Aggregate(new StringBuilder(), (f, s) => f.AppendFormat("{0:X2}", s)).ToString(0, length);
    }

答案 2 :(得分:5)

尝试以下方法:

var builder = new StringBuilder();
while(builder.Length < idLength) 
{
  builder.Append(Guid.NewGuid().ToString());
}
return builder.ToString(0, idLength);

如果您需要的是一种能够为测试目的生成垃圾的方法,那么以下可能更合适:

private static Random Random = new Random();
public static string GenerateRandomString(int length, string characterSet = "abcdefghijklmnopqrstuvwxyzABCDDEFGHIJKLMNOPQRSTUVWXYZ")
{
    var builder = new StringBuilder();
    while(builder.Length < length) 
    {
        builder.Append(characterSet.Chars[Random.Next(characterSet.Length)]);
    }
    return builder.ToString();
}

顺便说一句,当随机化测试值时,我更喜欢仍然给我的属性描述性名称,因为我发现失败消息通常更有帮助。我为此目的使用扩展方法:

private static Random Random = new Random();
public static string Randomise(this string value)
{
  return value + Random.Next();
}

在我的测试中可以使用哪种方式:

var customer = new Customer { Id = "CustomerId".Randomise() };

这可能不适用于这种情况,因为需要给定长度的字符串,但是如果/当测试失败时它会节省一些时间。

答案 3 :(得分:4)

注意:具有用户定义长度的GUID不再是GUID。

也就是说,如果要生成类似于给定长度的GUID 的字符串,请尝试类似以下(未经测试的)代码。

string myMethod(int length)
{
    StringBuilder myGuidLikeString = new StringBuilder();
    while(myGuidLikeString.Length < length)
    {
        myGuidLikeString .Append(Guid.NewGuid.ToString());
    }
    return myGuidLikeString.ToString(0,length);
}

哎呀 - rich.okelly以一种几乎相同的方法击败我。