私の静的なC#関数はば完全に奇妙な...私と一緒にゲームをプレイしています!
-
26-09-2019 - |
質問
だから、私はC#に小さくて、私が最初に思ったから、簡単な方法を書いています。 この静的メソッドは、単純なパスワードの提案発生器として使用されることを意図しており、このようなコードのルックスされます:
public static string CreateRandomPassword(int outputLength, string source = "")
{
var output = string.Empty;
for (var i = 0; i < outputLength; i++)
{
var randomObj = new Random();
output += source.Substring(randomObj.Next(source.Length), 1);
}
return output;
}
私はこのように、この関数を呼び出します:
var randomPassword = StringHelper.CreateRandomPassword(5, "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890");
さて、この方法はほとんど常に「BBBBBB」、「888888」等。、私はそれが「82mOK7」など、「A8JK2A」のような文字列を返すべきと思ったところ、「AAAAAA」のようなランダムな文字列を返す。
しかし、ここで奇妙一部です。私は、ブレークポイント、およびラインによって、この反復ラインを介してステップを配置する場合、私はお返しに、パスワードの正しい種類を取得します。イムは、デバッグしない場合は、他の例は100%で、それは「666666」、など。
、私は「AAAAAA」のようながらくたいますこれはどのように可能ですか?任意の提案は大歓迎です! : - )
ところで、私のシステム:/ ASP.NET開発サーバーワットのVisual Studio 2010、C#4.0、ASP.NET MVC 3 RTMプロジェクト。任意の他の環境でこのコードをテストしていません。
解決
ループの外側randomObjの宣言を移動します。あなたがそれをデバッグしているときに種子が異なるようにするために十分な時間差がありますので、それは、新しいシードたびに、それを作成します。デバッグしていないとき、それはあなたのたびに同じ開始値を与えているのでしかし、シード時間は、ループの各反復のために基本的に同じである。
とマイナーのNIT - それはあなたが再初期化のメモリ空間には、文字列に文字を追加するたびに持っていないので、この種のもののためにStringBuilderのではなく、文字列を使用することは良い習慣です。
このようなつまり、
public static string CreateRandomPassword(int outputLength, string source = "")
{
var output = new StringBuilder();
var randomObj = new Random();
for (var i = 0; i < outputLength; i++)
{
output.Append(source.Substring(randomObj.Next(source.Length), 1));
}
return output.ToString();
}
他のヒント
行動ますRandom
であるためだシーイングがあるの時間ベースを、としたときに、デバッグしていない、それは同じ瞬間に、すべての5回の反復を飛行(多かれ少なかれ)。あなたは同じシードから最初の乱数を求めているので。あなたのしているデバッグ、それは新しいシードを毎回取得するために十分な長さをとるときます。
ループ外Random
の宣言を移動
var randomObj = new Random();
for (var i = 0; i < outputLength; i++)
{
output += source.Substring(randomObj.Next(source.Length), 1);
}
今しているの 5歩の距離ランダムシードの代わりにを同じランダムシードから1歩動いて5回のから前進します。
あなたは新しい時間依存の種とループを通して各反復でランダム()の新しいインスタンスをインスタンス化しています。システムクロックと現代のCPUの速度の精度を考えると、これはかなりの保証はあなたが何度も同じシードで擬似ランダムシーケンスを再起動すること。
しかし、あなたしているが、シングルスレッドの場合は、あなたが安全に)(ロックを省略することができ、次のようなものを試してみてください
private static Random randomBits = new Random() ;
public static string CreateRandomPassword(int outputLength, string source = "")
{
StringBuilder sb = new StringBuilder(outputLength) ;
lock ( randomBits )
{
while ( sb.Length < outputLength )
{
sb.Append( randomBits.Next( source.Length) , 1 ) ;
}
}
return sb.ToString() ;
}
あなたは一度だけRNGをインスタンス化します。それはエントロピーの源のようにはるかに振る舞う必要がありますので、すべては、同じRNGからのビットを描画します。あなたがテスト用に再現が必要な場合は、種子を供給することができますランダムコンストラクタのオーバーロードを使用します。同じシード==同じ擬似ランダム系列ます。