質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

2回答

652閲覧

[C#]for分の実行時の動作

Cik_imi

総合スコア12

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

0クリップ

投稿2020/02/26 08:08

前提・実現したいこと

ランダムな文字列を得たいため、ごく普通と思うコードをプログラムしました。
C#,WPF,MVVMで簡単なコードですが、for文の中で文字列を生成しています。

発生している問題・エラーメッセージ

for文の中でStringBuilderにて別な関数にて生成した文字列を取得していますが、Thread.Sleep(20);の遅延?を入れないと、戻り値である複数行の文字列は同じになってしまいます。
なぜ、下記のようになるか理由・原因等をお教えいただきたくお願いします。

該当のソースコード

Models:
class RandomStr
{
private static readonly string NumStrChars = "0123456789";
// 一部を除く l
private static readonly string SmallStrChars = "abcdefghijkmnopqrstuvwxyz";
// 一部を除く I,O
private static readonly string LargeStrChars = "ABCDEFGHJKLMNPQRSTUVWXYZ";
// 記号は全部を除く
private static readonly string SymbolStrChars = "";
// 数字を含む
private string SrcStr = NumStrChars + SmallStrChars + LargeStrChars + SymbolStrChars;

public string GenerateRandomStr(int length) { StringBuilder sb = new StringBuilder(length); Random r = new Random(); int lenStr = SrcStr.Length; for (int i = 0; i < (length -1); i++) sb.Append(SrcStr[r.Next(lenStr)]); return sb.ToString(); }

}

ViewModels:
class MainViewModel
{
public string Rstr
{
get { return StrRandomStr(5); }
set { }
}

private string StrRandomStr(int n) { var rs = new Models.RandomStr(); StringBuilder sbr = new StringBuilder(); for (int i = 0; i< n; i++) { sbr.Append(rs.GenerateRandomStr(8)); sbr.Append(Environment.NewLine); Thread.Sleep(20); // ← これを入れないと全部同じ値を返す } return ("Result =====" + Environment.NewLine + sbr.ToString()); }

}

試したこと

実行例を示します。
例:Sleep(0)の場合
Result =====
J29DeMas
J29DeMas
J29DeMas
J29DeMas
J29DeMas

例:Sleep(20)の場合
Result =====
BrTeBYfj
nQf34WAn
edKfQ2iU
wVWF31tW
G1Ah36nu

ハードウェアの違いかと思い、2台のPCで実行しましたが、同様な結果になりました。

補足情報(FW/ツールのバージョンなど)

ツールは Visual Studio Community 2017 です。

参考ウェブサイト
https://dobon.net/vb/dotnet/string/generatepassword.html

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Random r = new Random();
このようにSeed値を指定せずにインスタンスを生成した場合、Environment.TickCountがSeed値として使用されます。
この為、短時間でインスタンスを生成する場合はSeed値が同じになってしまいます。
kawa0x0Aさんの回答のようにインスタンスを使いまわすようにするかSeed値が同一にならないようにインスタンスを生成するかする必要があります。

こちらにあるようにRNGCryptoServiceProviderクラスを使用する手もあります。

投稿2020/02/26 08:35

YAmaGNZ

総合スコア10258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Cik_imi

2020/02/26 09:16

回答をいただきありがとうございました。 オブジェクトの使い方によるものであるため、教えていただいたクラスでのコード等に修正してみたいと思います。
guest

0

ベストアンサー

https://docs.microsoft.com/ja-jp/dotnet/api/system.random?view=netframework-4.8

「乱数ジェネレーターのインスタンス化」の項目には次のように書かれています。

ほとんどの Windows システムでは、15ミリ秒以内に作成された Random オブジェクトのシード値が同一である可能性があります。

Sleepメソッドを実行しない場合ではRandomオブジェクトのシード値が同一になっていると思われます。
シード値が同じなので、Nextメソッドで値を取得しても同じ値が返ってきてしまいます。

この問題を解決したい場合はRandomオブジェクトをクラスのメンバ変数にして一度だけ初期化するなどの方法が考えられます。

投稿2020/02/26 08:15

編集2020/02/26 08:41
kawa0x0A

総合スコア271

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Cik_imi

2020/02/26 09:13

回答をいただきありがとうございました。 Randomオブジェクトによるものとは、思っていませんでした。 コードを修正したいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問