Asp.net 随机字符串生成器在多个调用中创建相同的字符串
我已经构建了一个随机字符串生成器,但是我遇到了一个问题,如果我多次调用该函数(比如在Page_Load方法中),该函数将返回相同的字符串两次 这是密码Asp.net 随机字符串生成器在多个调用中创建相同的字符串,asp.net,vb.net,string,random,Asp.net,Vb.net,String,Random,我已经构建了一个随机字符串生成器,但是我遇到了一个问题,如果我多次调用该函数(比如在Page_Load方法中),该函数将返回相同的字符串两次 这是密码 Public Class CustomStrings ''' <summary>' ''' Generates a Random String' ''' </summary>' ''' <param name="n">number of characters the method
Public Class CustomStrings
''' <summary>'
''' Generates a Random String'
''' </summary>'
''' <param name="n">number of characters the method should generate</param>'
''' <param name="UseSpecial">should the method include special characters? IE: # ,$, !, etc.</param>'
''' <param name="SpecialOnly">should the method include only the special characters and excludes alpha numeric</param>'
''' <returns>a random string n characters long</returns>'
Public Function GenerateRandom(ByVal n As Integer, Optional ByVal UseSpecial As Boolean = True, Optional ByVal SpecialOnly As Boolean = False) As String
Dim chars As String() ' a character array to use when generating a random string'
Dim ichars As Integer = 74 'number of characters to use out of the chars string'
Dim schars As Integer = 0 ' number of characters to skip out of the characters string'
chars = { _
"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", "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", "!", "@", "#", "$", _
"%", "^", "&", "*", "(", ")", _
"-", "+"}
If Not UseSpecial Then ichars = 62 ' only use the alpha numeric characters out of "char"'
If SpecialOnly Then schars = 62 : ichars = 74 ' skip the alpha numeric characters out of "char"'
Dim rnd As New Random()
Dim random As String = String.Empty
Dim i As Integer = 0
While i < n
random += chars(rnd.[Next](schars, ichars))
System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
End While
rnd = Nothing
Return random
End Function
End Class
答案是这样的
Dim rnd1 As New CustomStrings
Dim rnd2 As New CustomStrings
Dim str1 As String = rnd1.GenerateRandom(5)
Dim str2 As String = rnd2.GenerateRandom(5)
rnd1 = Nothing
rnd2 = Nothing
g*3Jqg*3Jq 第二次我叫它的时候,它会 3QM0$
3QM0$
我错过了什么?我希望生成的每个随机字符串都是唯一的。原因是,当您构造
random
类的实例时,它会从时钟中为自己播种,但如果您快速连续地调用它,则该时钟的精度不足以在每次调用中生成新的种子
换言之,这:
Random r = new Random();
int i = r.Next(1000);
r = new Random();
int j = r.Next(1000);
在i
和j
中产生相同值的概率非常高
您需要做的是:
- 创建并缓存
实例,使其与每次调用使用的实例相同(但不幸的是,该类不是线程安全的,因此至少为每个线程保留一个缓存副本)Random
- 用每次调用都会发生变化的内容对其进行种子设定(这相当困难,因为用顺序值对其进行种子设定会产生可预测的随机数)
Random
实例,并从全局随机对象中为这些实例种子。同样,这可能会产生可预测的序列
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SO2755146
{
public class Program
{
public static void Main()
{
List<Task> tasks = new List<Task>();
for (int index = 0; index < 1000; index++)
tasks.Add(Task.Factory.StartNew(() => Console.Out.WriteLine(RNG.Instance.Next(1000))));
Task.WaitAll(tasks.ToArray());
}
}
public static class RNG
{
private static Random _GlobalSeed = new Random();
private static object _GlobalSeedLock = new object();
[ThreadStatic]
private static Random _Instance;
public static Random Instance
{
get
{
if (_Instance == null)
{
lock (_GlobalSeedLock)
{
_Instance = new Random(_GlobalSeed.Next());
}
}
return _Instance;
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Threading.Tasks;
名称空间SO2755146
{
公共课程
{
公共静态void Main()
{
列表任务=新列表();
对于(int-index=0;index<1000;index++)
tasks.Add(Task.Factory.StartNew(()=>Console.Out.WriteLine(RNG.Instance.Next(1000)));
Task.WaitAll(tasks.ToArray());
}
}
公共静态类RNG
{
private static Random_GlobalSeed=new Random();
私有静态对象_GlobalSeedLock=新对象();
[线程静态]
私有静态随机实例;
公共静态随机实例
{
得到
{
if(_Instance==null)
{
锁(_GlobalSeedLock)
{
_Instance=newrandom(_GlobalSeed.Next());
}
}
返回_实例;
}
}
}
}
如果您只想从时钟中为每个随机实例设定种子,但至少要为每个线程生成随机序列,可以将其简化为:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SO2755146
{
public class Program
{
public static void Main()
{
List<Task> tasks = new List<Task>();
for (int index = 0; index < 1000; index++)
tasks.Add(Task.Factory.StartNew(() => Console.Out.WriteLine(RNG.Instance.Next(1000))));
Task.WaitAll(tasks.ToArray());
}
}
public static class RNG
{
[ThreadStatic]
private static Random _Instance;
public static Random Instance
{
get
{
if (_Instance == null)
_Instance = new Random();
return _Instance;
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Threading.Tasks;
名称空间SO2755146
{
公共课程
{
公共静态void Main()
{
列表任务=新列表();
对于(int-index=0;index<1000;index++)
tasks.Add(Task.Factory.StartNew(()=>Console.Out.WriteLine(RNG.Instance.Next(1000)));
Task.WaitAll(tasks.ToArray());
}
}
公共静态类RNG
{
[线程静态]
私有静态随机实例;
公共静态随机实例
{
得到
{
if(_Instance==null)
_Instance=newrandom();
返回_实例;
}
}
}
}
这可能会使两个线程开始时彼此非常接近,以相同的值作为种子,因此存在一个折衷。我做了一些更改,对我来说似乎很好。我不喜欢使用关键字作为变量名。请注意,我移动了随机语句:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim myCS As New CustomStrings
Dim l As New List(Of String)
For x As Integer = 1 To 10
Dim s As String = myCS.GenerateRandom(5)
l.Add(s)
Next
For x As Integer = 0 To l.Count - 1
Debug.WriteLine(l(x))
Next
'Debug output
'YGXiV
'rfLmP
'OVUW9
'$uaMt
'^RsPz
'k&91k
'(n2uN
'ldbQQ
'zYlP!
'30kNt
End Sub
Public Class CustomStrings
Private myRnd As New Random()
Public Function GenerateRandom(ByVal n As Integer, _
Optional ByVal UseSpecial As Boolean = True, _
Optional ByVal SpecialOnly As Boolean = False) As String
Dim ichars As Integer = 74 'number of characters to use out of the chars string'
Dim schars As Integer = 0 ' number of characters to skip out of the characters string'
Dim chars() As Char = New Char() {"A"c, "B"c, "C"c, "D"c, "E"c, "F"c, _
"G"c, "H"c, "I"c, "J"c, "K"c, "L"c, _
"M"c, "N"c, "O"c, "P"c, "Q"c, "R"c, _
"S"c, "T"c, "U"c, "V"c, "W"c, "X"c, _
"Y"c, "Z"c, "0"c, "1"c, "2"c, "3"c, _
"4"c, "5"c, "6"c, "7"c, "8"c, "9"c, _
"a"c, "b"c, "c"c, "d"c, "e"c, "f"c, _
"g"c, "h"c, "i"c, "j"c, "k"c, "l"c, _
"m"c, "n"c, "o"c, "p"c, "q"c, "r"c, _
"s"c, "t"c, "u"c, "v"c, "w"c, "x"c, _
"y"c, "z"c, "!"c, "@"c, "#"c, "$"c, _
"%"c, "^"c, "&"c, "*"c, "("c, ")"c, _
"-"c, "+"c}
If Not UseSpecial Then ichars = 62 ' only use the alpha numeric characters out of "char"'
If SpecialOnly Then schars = 62 : ichars = 74 ' skip the alpha numeric characters out of "char"'
Dim rndStr As String = String.Empty
Dim i As Integer = 0
While i < n
rndStr += chars(Me.myRnd.Next(schars, ichars))
System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
End While
Return rndStr
End Function
End Class
End Class
公共类表单1
私有子按钮1\u单击(ByVal sender作为System.Object,ByVal e作为System.EventArgs)处理按钮1。单击
将myCS设置为新的自定义字符串
Dim l作为新列表(字符串)
对于x作为整数=1到10
Dim s As String=myCS.generateradom(5)
l、 加
下一个
对于x为整数=0到l。计数为-1
调试写入线(l(x))
下一个
'调试输出
"YGXiV
“rfLmP
“OVUW9
“$uaMt
“^RsPz
'k&91k
"(n2uN)
“ldbQQ
“zYlP!
'30kNt
端接头
公共类自定义字符串
私有myRnd作为新的Random()
公共函数生成器域(ByVal n为整数_
可选的ByVal UseSpessional作为布尔值=True_
可选的ByVal(特别是Boolean=False)作为字符串
Dim ichars As Integer=74'字符字符串中要使用的字符数'
Dim schars As Integer=0“要从字符串中跳过的字符数”
Dim chars()As Char=New Char(){“A”c,“B”c,“c”c,“D”c,“E”c,“F”c_
“G”c,“H”c,“I”c,“J”c,“K”c,“L”c_
“M”c,“N”c,“O”c,“P”c,“Q”c,“R”c_
“S”c,“T”c,“U”c,“V”c,“W”c,“X”c_
“Y”c、“Z”c、“0”c、“1”c、“2”c、“3”c、_
“4”c、“5”c、“6”c、“7”c、“8”c、“9”c、_
“a”c,“b”c,“c”c,“d”c,“e”c,“f”c_
“g”c,“h”c,“i”c,“j”c,“k”c,“l”c_
“m”c,“n”c,“o”c,“p”c,“q”c,“r”c_
“s”c,“t”c,“u”c,“v”c,“w”c,“x”c_
“y”c,“z”c,“!”c,“@”c,“#”c,“$”c_
“%”c、“^”c、“*”c、“(”c“)”c、_
“-”c“+”c}
如果不使用特殊字符,则ichars=62'仅使用“char”中的字母数字字符'
如果是特殊情况,则schars=62:ichars=74'跳过“char”中的字母数字字符'
作为Stri的Dim rndStr
Private Function GetNewSeed() As Integer
Dim arrBytes As Byte() = Guid.NewGuid().ToByteArray() '16 bytes
Dim seedNum As Integer = 0
' Boil GUID down 4 bytes at a time (size of int) and merge into Integer value
For i As Integer = 0 To arrBytes.Length - 1 Step 4
seedNum = seedNum Xor BitConverter.ToInt32(arrBytes, i)
Next
Return seedNum
End Function
Dim rnd1 As New Random( GetNewSeed )
Session["seedRandom"] = 1;
private string getRandAlphaNum()
{
int seed_value = (int)DateTime.Now.Ticks;
seed_value = seed_value + Int32.Parse(Session["seedRandom"].ToString());
//change the Session variable by incrementing its value to 1 after creating seed value.
Session["seedRandom"] = Int32.Parse(Session["seedRandom"].ToString()) + 1;
Random rand = new Random(seed_value);
.....
.....
}