.NET Frameworkにおいて、Randomクラスのコンストラクタでシード値を指定しなかった場合は、デフォルト値としてシステム時計の値(インスタンスを生成するときのEnvironment.TickCountの値)が使用されます。 このため、実行するタイミングによって毎回異なるシード値のインスタンスが作成されることになります。 ただし、Environment.TickCountの値は短時間に連続して取得すると同じ値が返される場合があります。 これにより、シード値を指定せず、短時間で複数のRandomクラスのインスタンスを連続して生成すると、同一のシード値からなるインスタンス(つまり同一の乱数系列)が生成される可能性がある点に注意する必要があります。
.NET Core/.NET 5以降では、デフォルトのシード値自体も別の乱数系列から取得されるため、インスタンスごとに毎回異なるシード値が与えられます。
短時間に連続してRandomインスタンスを作成する場合のシード値
Imports System
Imports System.Threading
Class Sample
Shared Sub Main()
' シード値を指定せずにインスタンスを連続して生成する
' ・.NET Frameworkでは、デフォルトのシード値としてEnvironment.TickCountの値が用いられるため
' 連続して作成したインスタンスが同一のシード値を持つ場合がある
' ・.NET Core/.NET 5では、Environment.TickCountではなく呼び出し毎に異なるシード値を用いるため、
' 連続して作成した場合でもインスタンスが同一のシード値を持つことはない
' (RandomNumberGenerator相当から取得されるシード値を元にグローバルなRandomが作成され、
' そこから得られる乱数がシード値として用いられる)
Dim rand1 As New Random()
Dim rand2 As New Random()
Thread.Sleep(100) ' 100ミリ秒待機
' シード値を指定せずにインスタンスを生成
Dim rand3 As New Random()
Const format As String = "{0,-6} {1,-6} {2,-6}"
Console.WriteLine(
format,
NameOf(rand1),
NameOf(rand2),
NameOf(rand3)
)
' 各インスタンスから乱数を生成して表示する
For i As Integer = 1 To 15
Console.WriteLine(
format,
rand1.Next(0, 100),
rand2.Next(0, 100),
rand3.Next(0, 100)
)
Next
End Sub
End Class
.NET Frameworkでの実行結果例
rand1 rand2 rand3 51 51 55 78 78 55 88 88 36 62 62 2 18 18 36 6 6 37 35 35 91 25 25 13 66 66 67 47 47 28 42 42 1 23 23 79 4 4 53 4 4 14 48 48 70
.NET Coreでの実行結果例
rand1 rand2 rand3 94 68 94 89 88 31 28 3 74 97 15 88 36 73 44 57 41 52 12 69 71 37 79 41 27 14 16 89 67 18 52 98 39 81 51 38 0 18 17 48 90 11 18 80 61