我应该缓存RNGCryptoServiceProvider/RandomNumberGenerator实例吗?

jul*_*gon 10 .net random performance caching cryptography

我已经阅读了很多次关于Regex类的效率以及调用它的静态方法或缓存正则表达式实例的重要性.

如果我RNGCryptoServiceProvider多次实例化该类而不是缓存该类的单个实例并调用GetBytes它,我想知道是否可以观察到相同的问题.

每次我需要一个随机数时实例化它会简化我的代码,因为我不必担心一次性实例挂起并IDisposable在一堆类中传播一个接口.

我唯一发现的是创建一个RNGCryptoServiceProvider的实例应该非常快,但我仍然希望看到确认,最佳实践是什么.

如果我每次实例化该类而不是使用相同的实例,那么生成的随机数是否也会有任何差异?

Mik*_*sdf 17

使用默认构造函数重复构造不应对性能或随机性质量产生任何不良影响.

我们来看看源代码......

#if !FEATURE_PAL
        [System.Security.SecuritySafeCritical]  // auto-generated
        public RNGCryptoServiceProvider() : this((CspParameters) null) {} 
#else // !FEATURE_PAL
        public RNGCryptoServiceProvider() { } 
#endif // !FEATURE_PAL 
Run Code Online (Sandbox Code Playgroud)

FEATURE_PAL指令与windows与非Windows平台有关.但我们不需要知道细节; 让我们看一下真假案例.

首先,很明显,如果启用了FEATURE_PAL,则默认构造函数中没有代码.

在另一种情况下,构造函数使用null CspParameters调用特定的构造函数.那个其他构造函数看起来像这样:

[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; 
   } 
}
Run Code Online (Sandbox Code Playgroud)

cspParams将始终为null,因此构造函数的值为Utils.StaticProvHandle.那个getter看起来像这样:

#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;
            } 
        }
#endif // !FEATURE_PAL 
Run Code Online (Sandbox Code Playgroud)

它由静态变量支持.getter在第一次初始化时使用了一些锁,但后续调用只返回静态变量.

现在让我们回顾一下RNGCryptoServiceProvider.cs并查看Dispose方法:

[System.Security.SecuritySafeCritical]  // auto-generated
protected override void Dispose(bool disposing) {
   base.Dispose(disposing);

   if (disposing && m_ownsHandle) {
         m_safeProvHandle.Dispose(); 
   } 
}
Run Code Online (Sandbox Code Playgroud)

m_ownsHandle 如果调用了默认构造函数,则为false,因此它永远不会处置任何内容.

因此,在每个构造+处理期间发生的所有事情都是一些简单的变量访

  • 尝试使“重复构造不应对性能或随机性质量产生任何不良影响”作为第一个陈述是此响应。有兴趣的可以阅读如何。+1 给你。 (2认同)