我使用这个C#函数来生成一个系统的随机优惠券。我该如何改进呢?
public static string GenerateCoupon(int length)
{
string result = string.Empty;
Random random = new Random((int)DateTime.Now.Ticks);
List<string> characters = new List<string>() { };
for (int i = 48; i < 58; i++)
{
characters.Add(((char)i).ToString());
}
for (int i = 65; i < 91; i++)
{
characters.Add(((char)i).ToString());
}
for (int i = 97; i < 123; i++)
{
characters.Add(((char)i).ToString());
}
for (int i = 0; i < length; i++)
{
result += characters[random.Next(0, characters.Count)];
Thread.Sleep(1);
}
return result;
}业务要求是:
发布于 2011-11-12 22:21:10
让我们看看其中的一些代码:
Random random = new Random((int)DateTime.Now.Ticks);您不需要从时钟中为随机构造函数创建种子,无参数构造函数可以这样做:
Random random = new Random();List<string> characters = new List<string>() { };如果没有在列表中添加任何项目,则不需要初始化括号:
List<string> characters = new List<string>();result += characters[random.Next(0, characters.Count)];使用+=连接字符串是错误的做法。字符串不追加在末尾,因为字符串是不可变的。像x += y;这样的代码实际上以x = String.Concat(x, y)结束。您应该使用StringBuilder来构建字符串。
Thread.Sleep(1);你到底为什么睡在圈中间?
与其创建字符串列表,不如使用字符串文本从以下位置选择字符:
public static string GenerateCoupon(int length) {
Random random = new Random();
string characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++) {
result.Append(characters[random.Next(characters.Length)]);
}
return result.ToString();
}考虑是否应该包括所有这些字符,或者忽略类似的字符,如o、O和0。使用字符串文字中的字符可以很容易地做到这一点。
如果要多次调用该方法,则应将随机生成器作为参数发送:
public static string GenerateCoupon(int length, Random random) {
string characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++) {
result.Append(characters[random.Next(characters.Length)]);
}
return result.ToString();
}用法:
Random rnd = new Random();
string[] coupon = new string[10];
for (int i = 0; i < coupon.Length; i++) {
coupon[i] = GenerateCoupon(10, rnd);
}
Console.WriteLine(String.Join(Environment.NewLine,coupon));示例输出:
LHUSer9dPZ
btK0S01yLb
hruw4IXINJ
hwMdRDRujt
cr4TDezvcZ
b8tVETNXNL
JrG6sfXgZF
Y7FRypnRiQ
JbfnhY3qOx
quWNakbybY发布于 2011-11-14 00:00:15
您不应该使用Random来生成优惠券。您的优惠券在某种程度上是可以预测的:如果有人可以看到一些优惠券(特别是几张连续的优惠券),他们将能够重建种子并生成所有的优惠券。对于大多数数字模拟和一些游戏来说,Random是可以的,当您需要生成不可预测的值时,这一点也不太好。你的优惠券就像密码,你需要密码质量的随机性。幸运的是,C#库中有一个密码质量的随机生成器:System.Security.Cryptography.RNGCryptoServiceProvider。
这个RNG返回字节。一个字节中有256个可能的值。您的优惠券只能使用62个字符中的一个,因此您需要拒绝不映射到ASCII字母或数字的字节。
此外,在逐块构建字符串时,您应该使用使用StringBuilder。当您完成构建它时,将其解析为字符串。
var couponLength = 32;
StringBuilder coupon = new StringBuilder(couponLength);
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] rnd = new byte[1];
int n = 0;
while (n < couponLength) {
rng.GetBytes(rnd);
char c = (char)rnd[0];
if ((Char.IsDigit(c) || Char.IsLetter(c)) && rnd[0] < 127) {
++n;
coupon.Append(c);
}
}
return coupon.ToString();通过拒绝较少的值,您可以使生成速度提高大约4倍。不要只接受映射到您想要的字符的62个值,除以4得到64个等概率值中的一个,并接受其中的62个(将它们映射到正确的字符)并拒绝2。
while (n < couponLength) {
rng.GetBytes(rnd);
rnd[0] %= 64;
if (rnd[0] < 62) {
++n;
coupon.Append((char)((rnd[0] <= 9 ? '0' : rnd[0] <= 35 ? 'A' - 10 : 'a' - 36) + rnd[0]);
}
}发布于 2011-11-12 13:04:33
一些一般性的想法,我希望所有的工作在C#也。如果答案不是正确的C#语法,请随意编辑它。
1,将characters列表的类型更改为char,并将循环变量也更改为char。这样您就不需要强制转换了,for循环更容易读懂:
List<char> characters = new List<char>() { };
for (char c = '0'; i <= '9'; c++) {
characters.Add(c);
}
...
for (int i = 0; i < length; i++){
result += characters[random.Next(0, characters.Count)];
}2、是否存在Thread.Sleep(1);的原因?看起来没必要。
我要把0,O,o和l,1从名单上删除。很容易把它们混在一起。
4 .我会提取一个AllowedCharacters方法:
public static List<char> AllowedCharacters() {
List<char> characters = new List<char>() { };
for (char c = '0'; i <= '9'; c++) {
characters.Add(c);
}
...
characters.Remove('O');
characters.Remove('0');
...
return characters;
}
public static string GenerateCoupon(int length)
{
string result = string.Empty;
Random random = new Random((int)DateTime.Now.Ticks);
List<string> characters = AllowedCharacters();
for (int i = 0; i < length; i++) {
result += characters[random.Next(0, characters.Count)];
}
return result;
}https://codereview.stackexchange.com/questions/5983
复制相似问题