根据RandomNumberGenerator的MSDN文档:
应用程序代码不直接使用此类。此抽象类作为所有加密随机数生成器的基类提供。
对于加密随机数生成器的实现,请使用派生类RNGCryptoServiceProvider。
但是,我已经看到以下代码在不同代码库中的几个场景中使用:
byte[] bytes = new byte[...];
RandomNumberGenerator rng = RandomNumberGenerator.Create();
rng.GetBytes(bytes);
最值得注意的是StackExchange(我假设包含SO)以及BCrypt.Net。
因此,我有点困惑 - 上面的代码返回的是什么类型的RandomNumberGenerator
?使用RandomNumberGenerator
而非RNGCryptoServiceProvider
的某些代码库是还有一点缺陷吗?
我认为RandomNumberGenerator.Create()
在幕后做了我在这里完全没有,但从技术上讲(因为它是一个抽象类)上面的代码不应该抛出错误吗?
答案 0 :(得分:18)
RandomNumberGenerator.Create()
方法调用RandomNumberGenerator.Create("System.Security.Cryptography.RandomNumberGenerator")
,最终会创建RNGCryptoServiceProvider
的实例。
(它在一对字典中进行一些查找,因此您可以通过在某处注册默认随机生成器来更改该调用的行为。)
返回的对象的实际类型在编译时是未知的,只知道它将继承RandomNumberGenerator
类,因此您可以使用RandomNumberGenerator
引用变量。
这种根据输入创建不同类型实例的方法在框架中的几个地方使用,例如WebRequest.Create
方法。
Micrsoft的某个人“修复了”Create()
方法的当前文档(框架4.5)。它现在说:
“在派生类中重写时,创建一个实例 加密随机数生成器的默认实现 可以用来生成随机数据。“
框架4.0的文档说:
“创建加密的默认实现的实例 随机数生成器,可用于生成随机数据。“
这是该方法的正确描述。我将提出一个请求,将该描述放回到较新的文档中。
答案 1 :(得分:3)
RandomNumberGenerator
的文档基本搞砸了。另一个例子,有这样的文档:
在派生类中重写时,创建加密随机数生成器的指定实现的实例。
...用于静态方法。静态方法无法被覆盖。谁清楚地写了这些文件并没有直接思考。
我怀疑最初的意图是:
应用程序代码不直接实例化此类。此抽象类作为所有加密随机数生成器的基类提供。
我认为你发布的代码(使用静态Create
方法)是完全合理的。它与XmlReader.Create
等使用的模式相同 - 静态方法选择最合适的实现。
答案 2 :(得分:1)
RandomNumberGenerator.Create
是一种静态工厂方法。当然它将返回派生类的实例。那个不是抽象的所以这一切都是合法的。
抽象类 make 可以在任何地方使用,而不是使用更具体的类。它们是一个版本友好的界面。