循环里用radom函数和DateTime.Now.Ticks注意要点

本文介绍了一种生成包含字母和数字的随机验证码的方法,并提供了一个将生成的验证码写入图像的具体实现,可用于网站登录验证等场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Drawing;

namespace Myth_Alpha_1._0.Business
{
     public class Function
     {
         /// <summary>
         /// 该方法用于生成指定长度的随机数
         /// </summary>
         /// <param name="VCodeNum">指定随机数的长度</param>
         /// <returns></returns>

         public static string RndNum(int VCodeNum)
         {
             string Vchar = "0,1,2,3,4,5,6,7,8,9,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,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[] VcArray = Vchar.Split(new char[] { ',' });
             string VNum = "";
             Random rnd ;
             int temp = -1;
             ////采用一个简单的算法保证随机数相临的两个不同和随机数的不同
             for (int i = 0; i < VCodeNum; i++)
             {
                 rnd = new Random((i+1)*unchecked((int)DateTime.Now.Ticks));

/******************************这里要注意*********************************

上面那句千万别写成rnd = new Random(unchecked((int)DateTime.Now.Ticks));因为下面那个if判断是用来避免出现两个相同的随机数的,而在一个for循环中,两次循环之间的时间间隔小到得到的DateTime.Now.Ticks的值是相同的,而导致Random(unchecked((int)DateTime.Now.Ticks))里面的种子相同,预期的随机数也一样. 在次程序中就导致了Over Flow异常!在调试次程序时,使用"执行不调试模式"一下子,程序就占用了1.8G的内存!

*********************************************************************/
                 int t = rnd.Next(61);
                 if (temp == t)
                 {
                     return RndNum(VCodeNum);
                 }
                 VNum += VcArray[t];
                 temp = t;
             }
             return VNum;
         }


         /// <summary>
         /// 将参数中的字符串写入图像(用做验证码)
         /// </summary>
         /// <param name="VNum">用做验证码的随机数</param>

         public static Bitmap ValidateCode(string VNum)
         {
             Bitmap image = new Bitmap(VNum.Length*14,22);
             Graphics g = Graphics.FromImage(image);
             Font f = new Font("Bradley Hand ITC", 13,FontStyle.Bold);
             SolidBrush b = new SolidBrush(Color.White);
             Point p = new Point(2,2);
             g.DrawString(VNum,f,b,p);

             g.Dispose();
             return image;
         }
     }
}

C# 中生成随机数通常使用 `Random` 类,该类提供了多种方法来生成不同类型的随机数。然而,在高并发或循环中频繁创建 `Random` 实例可能导致生成相同的随机数序列,因为默认种子基于系统时钟[^2]。为了避免这个问题,应尽量避免在循环内部重复创建 `Random` 实例。 ### 使用 Random 类生成随机数 以下是一个推荐的实现方式,确保每次生成的随机数具有更好的随机性: ```csharp Random random = new Random(); for (int i = 0; i < 10; i++) { Console.WriteLine(random.Next()); } ``` 上述代码仅初始化一次 `Random` 实例,并在循环内重复使用它来生成多个随机数,从而避免了因快速连续创建实例而导致的重复问题[^1]。 ### 生成指定范围的随机整数 可以使用 `Next(int minValue, int maxValue)` 方法生成特定范围内的整数: ```csharp Random random = new Random(); for (int i = 0; i < 10; i++) { Console.WriteLine(random.Next(1, 100)); // 生成 1 到 99 的随机整数 } ``` 这种方式适用于要求较低的场景,例如简单的游戏、模拟等。 ### 高并发环境下生成更可靠的随机数 由于 `Random` 类不是线程安全的,因此在多线程环境中需要额外处理以确保随机数的唯一性正确性。一种方法是将 `Random` 实例作为静态变量共享,或者在每个线程中使用独立的实例。 示例代码如下: ```csharp private static readonly Random GlobalRandom = new Random(); public static int GetRandomNumber(int min, int max) { lock (GlobalRandom) // 确保线程安全 { return GlobalRandom.Next(min, max); } } ``` ### 使用 Guid 生成随机数 另一种替代方案是利用 `Guid` 来生成伪随机字符串,尽管其随机性不如 `Random` 类强,但在某些特定场景下可能适用: ```csharp string randomString = Guid.NewGuid().ToString("N"); // 去除连字符 Console.WriteLine(randomString); ``` 此方法生成的是十六进制格式的字符串,适用于生成临时标识符或令牌。 ### 生成自定义字符集的随机字符串 如果需要从特定字符集中选取字符,可结合 `Random` 类实现: ```csharp private string GetRandomCode(string allChar, int codeCount) { string[] allCharArray = allChar.Split(','); StringBuilder randomCode = new StringBuilder(); int t = -1; Random rand = new Random(); for (int i = 0; i < codeCount; i++) { if (t != -1) { rand = new Random(t * i * ((int)DateTime.Now.Ticks)); } int e = rand.Next(allCharArray.Length); while (t == e) { e = rand.Next(allCharArray.Length); } t = e; randomCode.Append(allCharArray[e]); } return randomCode.ToString(); } ``` 该方法通过动态调整种子来提高随机性,适用于验证码、密码生成等场景[^3]。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值