19

根据RandomNumberGenerator的 MSDN 文档:

应用程序代码不直接使用此类。这个抽象类作为所有密码随机数生成器的基类提供。

对于加密随机数生成器的实现,请使用派生类 RNGCryptoServiceProvider。

但是,我在不同的代码库中看到了以下代码:

byte[] bytes = new byte[...];
RandomNumberGenerator rng = RandomNumberGenerator.Create();
rng.GetBytes(bytes);

最值得注意的是StackExchange(我假设它包括 SO)以及BCrypt.Net

因此,我有点困惑——RandomNumberGenerator上面的代码返回的是什么类型的?还有一些代码库使用RandomNumberGenerator而不是有点缺陷吗RNGCryptoServiceProvider

我假设RandomNumberGenerator.Create()是在幕后做的,我在这里完全错过了,但从技术上讲(因为它是一个抽象类)上面的代码不应该抛出错误吗?

4

3 回答 3

24

RandomNumberGenerator.Create()方法调用,最终将RandomNumberGenerator.Create("System.Security.Cryptography.RandomNumberGenerator")创建RNGCryptoServiceProvider.

(它会在一对字典中进行一些查找,因此您可能可以通过在某处注册默认随机生成器来更改该调用的行为。)

返回的对象的实际类型在编译时是未知的,只知道它将继承RandomNumberGenerator该类,因此您可以为其使用RandomNumberGenerator引用变量。

这种根据输入创建不同类型实例的方法在框架中的几个地方使用,例如通过WebRequest.Create方法。


Micrsoft 的某个人已经“修复”了该Create()方法的当前文档(框架 4.5)。它现在说:

“在派生类中重写时,创建可用于生成随机数据的加密随机数生成器的默认实现的实例。”

框架 4.0 的文档说:

“创建可用于生成随机数据的加密随机数生成器的默认实现的实例。”

这是对该方法作用的正确描述。我将请求将该描述放回较新的文档中。

于 2012-09-08T10:26:01.583 回答
4

的文档RandomNumberGenerator基本上是一团糟。作为另一个例子,有这样的文档:

在派生类中重写时,创建加密随机数生成器的指定实现的实例。

...对于静态方法。静态方法不能被覆盖。编写文档的人显然没有正确思考。

我怀疑最初的意图是这样的:

应用程序代码不直接实例化此类。这个抽象类作为所有密码随机数生成器的基类提供。

我认为您发布的代码(使用静态Create方法)是完全合理的。它与用于XmlReader.Createetc 的模式相同——静态方法选择最合适的实现。

于 2012-09-08T10:03:27.857 回答
2

RandomNumberGenerator.Create是静态工厂方法。它肯定会返回派生类的实例。而且那个不是抽象的,所以所有这些都是合法的。

抽象类可以任何地方使用,而不是使用更具体的类。它们旨在成为版本控制友好的界面。

于 2012-09-08T10:03:38.363 回答