早期使用 `Random.Next() % array.Length` 配合字串陣列 `Substring`,字串串聯在迴圈中效能極差。
public static string GenerateCaptcha(int length = 6)
{
const string chars = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"; // 排除易混淆 0/O 1/I
var random = new Random((int)DateTime.Now.Ticks);
var sb = new StringBuilder(length);
for (int i = 0; i < length; i++)
{
sb.Append(chars[random.Next(chars.Length)]);
}
return sb.ToString();
}
| 原寫法 | 改良版 |
|---|---|
| `text2 = text2 + ...` 字串不可變,產生大量暫時物件 | `StringBuilder` 可變緩衝區,單次配置 |
| `Substring(random.Next() % len, 1)` 兩次運算、建立子字串 | `chars[random.Next(chars.Length)]` 直接索引字元 |
| 字串常數 `textArray` 每次迴圈存取 | `const string chars` 編譯期內嵌,唯讀 |
using System.Security.Cryptography;
public static string GenerateSecureCaptcha(int length = 6)
{
const string chars = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
using (var rng = RandomNumberGenerator.Create())
{
var bytes = new byte[length];
rng.GetBytes(bytes);
var sb = new StringBuilder(length);
foreach (byte b in bytes)
sb.Append(chars[b % chars.Length]);
return sb.ToString();
}
}
StringBuilder + Random : ~180 ms StringBuilder + RNGCryptoSP : ~420 ms 舊版 Substring 串聯 : ~2,300 ms