Re-building using the default constructor should not have any negative consequences for performance quality or randomness.
Let's look at the source code ...
#if !FEATURE_PAL [System.Security.SecuritySafeCritical] // auto-generated public RNGCryptoServiceProvider() : this((CspParameters) null) {} #else // !FEATURE_PAL public RNGCryptoServiceProvider() { } #endif // !FEATURE_PAL
The FEATURE_PAL directive is related to windows and non-windows platforms. But we do not need to know the details; let's just look at the true and false cases.
First, itβs clear that if FEATURE_PAL is enabled, there is no code in the default constructor.
In another case, the constructor invokes a specific constructor with null CspParameters. This other constructor looks like this:
[System.Security.SecuritySafeCritical] // auto-generated public RNGCryptoServiceProvider(CspParameters cspParams) { if (cspParams != null) { m_safeProvHandle = Utils.AcquireProvHandle(cspParams); m_ownsHandle = true; } else { m_safeProvHandle = Utils.StaticProvHandle; m_ownsHandle = false; } }
cspParams will always be null, so the constructor gets the value Utils.StaticProvHandle . This receiver is as follows:
#if !FEATURE_PAL [System.Security.SecurityCritical /*auto-generated*/] private static SafeProvHandle _safeProvHandle = null; internal static SafeProvHandle StaticProvHandle { [System.Security.SecurityCritical] // auto-generated get { if (_safeProvHandle == null) { lock (InternalSyncObject) { if (_safeProvHandle == null) { SafeProvHandle safeProvHandle = AcquireProvHandle(new CspParameters(DefaultRsaProviderType)); Thread.MemoryBarrier(); _safeProvHandle = safeProvHandle; } } } return _safeProvHandle; } }
It is supported by a static variable. The getter uses some locks during the first initialization, but subsequent calls simply return a static variable.
Now look back at RNGCryptoServiceProvider.cs and look at the Dispose method:
[System.Security.SecuritySafeCritical]
m_ownsHandle is false if the default constructor was called, so it never has anything.
Thus, everything that happens during each build + is simple access to the variable.