I am migrating a method that is used for decoding from .NET Framework 1.1 to .NET Framework 4. I noticed that implementation of Random changed. So given the same seed, Random.NextBytes returns different result.
So if I run the following code.
byte[] bytes = new byte[4];
System.Random random = new System.Random(50);
random.NextBytes(bytes);
for(int i=0; i< bytes.Length; i++)
{
Console.WriteLine("bytes[" + i + "] = " + bytes[i]);
}
Under .NET Framework 1.1 it returns:
bytes[0] = 216
bytes[1] = 124
bytes[2] = 183
bytes[3] = 58
Under .NET framework 4 it returns:
bytes[0] = 154
bytes[1] = 49
bytes[2] = 183
bytes[3] = 48
What is the best way to resolve this problem?
Alternatively, might I suggest using
System.Security.Cryptography.RandomNumberGenerator
class to generate cryptographically strong random byte arrays?I will join the rest of the comments, and mention that relying on an undocumented implementation is bad. More so, if you're actually relying on a predictable "randomness" - if you're using this for anything that should be "secure" - it is totally wrong.
No answer here but contrary to many people here I don't think that documenting ridiculous behaviour is enough to justify it.
Because why would you provide a seeding mechanism in the first place? Well I'll tell you: so that you can always reproduce a random sequence from a single seed rather than having to persist perhaps millions of random numbers. Note that I said 'always', and not 'until you upgrade to the next version of .NET'. By not being consistent across versions the current .NET random number generators do not provide this functionality. Microsoft should have done a better job of implementing this (or not have implemented it at all) instead of just documenting the defective behaviour.
And by the way, although the algorithm is indeed an implementation detail, how on earth can you call the result of a method call an implementation detail? Should I really have to check the documentation of every method in the .NET framework to be sure that in the next version I do not risk getting a different result from concatenating two strings or calculating a square root?
So in my opinion what we have here is simply a badly implemented random number generator. And of course the entire problem could have been easily avoided by giving the new functionality (based on the new implementation) a different name.
You can just use Reflector to copy the Random class from the 1.1 mscorlib.
Tested and it gives the desired output.
If you're absolutely reliant on the .NET 1.1 version of Random then the only thing I can think of is to create a new assembly that targets 1.1 and call that from your upgraded .NET 4 application.
However, can you detail why it is so essential for you to maintain this seed? There might be a better way.
This is not a problem with
Random
, it satisfies its documented interface perfectly fine. This is a problem with your software relying on an implementation detail. Learn from this mistake and don't do it again.As far as fixing the problem, you can implement your own version of 1.1's pseudorandom number generation for decoding and then implement a new encoding/decoding algorithm that doesn't rely on unstable behavior (such as the implementation of
Random
orGetHashCode
) for your new version of the software.