首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我应该缓存RNGCryptoServiceProvider/RandomNumberGenerator实例吗?

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

Stack Overflow用户
提问于 2014-10-14 23:13:09
回答 1查看 1.3K关注 0票数 15

我已经读过很多次关于Regex类的效率以及调用它的静态方法或缓存regex实例有多重要。

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

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

关于这一点,我发现的唯一一点就是creating an instance of a RNGCryptoServiceProvider should be very fast,但我仍然希望看到确认以及最佳实践是什么。

如果每次实例化类与使用同一个实例,所生成的随机数是否也会有任何差异?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-21 17:59:32

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

让我们看看源代码..。

代码语言:javascript
复制
#if !FEATURE_PAL
        [System.Security.SecuritySafeCritical]  // auto-generated
        public RNGCryptoServiceProvider() : this((CspParameters) null) {} 
#else // !FEATURE_PAL
        public RNGCryptoServiceProvider() { } 
#endif // !FEATURE_PAL 

FEATURE_PAL指令与windows和非windows平台有关。但是我们不需要知道细节,让我们来看看真假两种情况。

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

在另一种情况下,构造函数用空CspParameters调用特定的构造函数。另一个构造函数如下所示:

代码语言:javascript
复制
[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将始终为null,因此构造函数将得到Utils.StaticProvHandle的值。那家伙看上去是这样的:

代码语言:javascript
复制
#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 

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

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

代码语言:javascript
复制
[System.Security.SecuritySafeCritical]  // auto-generated
protected override void Dispose(bool disposing) {
   base.Dispose(disposing);

   if (disposing && m_ownsHandle) {
         m_safeProvHandle.Dispose(); 
   } 
}

如果调用了默认构造函数,则m_ownsHandle是假的,因此它从不处理任何内容。

因此,在每个construction+disposal过程中发生的所有事情都是一些简单的变量访问。

票数 26
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26371951

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档