5

关于 .NET 中对不可为空的引用类型的支持存在许多问题。最大的希望是代码合约,但它仅限于预算有限的人的运行时检查。

至于代码合同以外的方法,Jon Skeet几年前写了一篇关于此的博客文章,其中一位评论者提供了一个看起来很有用的NonNull 结构,它修改了 IL 以禁用默认构造函数。这似乎是一种极好的方法,我可以想象将其扩展为提供各种不可为空的微类型。IL 操作可以是由结构上的属性触发的构建后步骤,例如

//Microtype representing a non-zero age, so we want to disable the default ctor
[NoDefaultConstructor]
public struct Age
{
    public Age(int age)
    {
        // Implementation (including validation) elided
    }
} 

在我进一步调查之前,我想问一下是否有人知道这可能导致的任何问题?我一个都想不出来。

4

1 回答 1

6

这可以很容易地被击败 - 运行时不会尝试在每个场景中调用结构(如果存在)的无参数构造函数。

特别是,它不会在创建结构类型的数组时被调用。

Age[] ages = new Age[3];

// This guy skips your "real" ctor as well as the "invalid" parameterless one.
Age age = ages[0];

...或在default(structType)表达式中:

// Invalid state here too.
Age age = default(Age);

根据 Jon Skeet 对这些东西的实证研究,这里列出了其他不调用构造函数的操作:

  • 只需声明一个变量,无论是本地的、静态的还是实例的
  • 拳击
  • default(T)在泛型方法中使用
  • new T()在泛型方法中使用

现在让您陷入困境的情况是,您必须以某种方式测试每个Age实例是否是通过在您的栅栏周围工作而创建的——这并不比一开始就没有竖立栅栏好多少。

于 2011-10-10T13:22:30.617 回答