出于测试目的,我使用给定的种子创建随机数(即不基于当前时间).
因此整个计划是确定性的.
如果发生了什么事情,我希望能够在"事件发生前不久"迅速恢复一个点.
因此,我需要能够恢复System.Random到以前的状态.
有没有办法提取种子,我可以用来重建随机生成器?
void Main()
{
var r = new Random();
Enumerable.Range(1, 5).Select(idx => r.Next()).Dump("before save");
var s = r.Save();
Enumerable.Range(1, 5).Select(idx => r.Next()).Dump("after save");
r = s.Restore();
Enumerable.Range(1, 5).Select(idx => r.Next()).Dump("after restore");
s.Dump();
}
public static class RandomExtensions
{
public static RandomState Save(this Random random)
{
var binaryFormatter = new BinaryFormatter();
using (var temp = new MemoryStream())
{
binaryFormatter.Serialize(temp, random);
return new RandomState(temp.ToArray());
}
}
public static Random Restore(this RandomState state)
{
var binaryFormatter = new BinaryFormatter();
using (var temp = new MemoryStream(state.State))
{
return (Random)binaryFormatter.Deserialize(temp);
}
}
}
public struct RandomState
{
public readonly byte[] State;
public RandomState(byte[] state)
{
State = state;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在LINQPad中测试此代码.
这是我想出来的:
基本上它提取私有种子数组。您只需要小心恢复“非共享”数组。
var first = new Random(100);
// gain access to private seed array of Random
var seedArrayInfo = typeof(Random).GetField("SeedArray", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var seedArray = seedArrayInfo.GetValue(first) as int[];
var other = new Random(200); // seed doesn't matter!
var seedArrayCopy = seedArray.ToArray(); // we need to copy since otherwise they share the array!
seedArrayInfo.SetValue(other, seedArrayCopy);
for (var i = 10; i < 1000; ++i)
{
var v1 = first.Next(i);
var v2 = other.Next(i);
Debug.Assert(v1 == v2);
}
Run Code Online (Sandbox Code Playgroud)