.NET 4.0中的代码契约,对于非可空引用类型的粉丝来说,没有什么乐趣?

时间:2009-10-01 09:18:52

标签: c# .net .net-4.0 c#-4.0 code-contracts

我一直在玩VS2008上的代码合约(http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx) 它们肯定很好,并为方法中的if-then-throw检查提供了一个可靠的替代方案。

尽管如此,我一直希望他们能够满足我对非可空引用类型的强烈感受。
唉,从我所看到的情况来看,情况似乎并非如此 这就是我的理解:

  • 这样的事情仍然会在运行时引起问题:
    MyClass a = null;
    a.ToString();

  • 我仍然必须明确地写支票,即使是以更简洁和简化的方式。

  • 除非您使用VS Team System,否则您只能使用代码合同在运行时检查事物,在编译时没有任何好处。
    这意味着当出现问题时你仍需要处理事情 与处理一个简单的例外没什么不同。

  • 即使使用VSTS,静态分析也不如在运行时完成的那样好 这是完全可以理解的,但这仍然是该功能用于运行时使用的另一个标志。

如果我错了,请纠正我,但从我看到的情况来看,Code Contracts无法使我的生活变得更轻松,而且我的程序更强大,就像非可空引用类型一样。

不要误解我的意思,我不喜欢代码合同 它们是整个框架的一个非常好的增强 只是如果这不能填补C#因没有非可空参考类型而离开的空白,此时我恐怕什么都不会。 你觉得怎么样?

5 个答案:

答案 0 :(得分:20)

我认为你对此是正确的。编译时不可空的引用检查是我在代码契约中等待的杀手级功能,它实际上并不存在。

对于那些想知道这意味着什么的人,请考虑与价值类型进行类比。它们最初不是可空的,但现在它们就是在类型名称后面加上一个问号:

int? n;

为了保持一致性,如果参考类型也是如此,那将是理想的。但这会破坏所有现有的C#程序,因此不是一种选择。在研究语言Spec#中,他们使用感叹号后缀表示不可为空:

string! s = "Hello";

与普通值类型一样,编译器在初始化之前静态检查string!变量在任何代码路径上都没有使用(我相信Spec#需要在同一语句中进行声明和初始化)。

它还禁止将null分配给该变量。

当然,它禁止将普通string分配给string!。那么如何弥合这两种类型之间的差距呢?写一张支票:

string x = GetStringFromSomewhere();

if (x != null)
    s = x; // okay because compiler sees null check

可悲的事实是,如果程序正确,大多数程序中的大多数参考变量可能是不可为空的。可空变量属于少数。但它们是默认值。

Another bad idea from the 1960s

答案 1 :(得分:3)

我不确定“非可空引用类型”解决了什么问题。好的,所以这段代码不太可能抛出异常: -

a.ToString();

然而,它是否可能正确,因为它不可为空? a的初始值是多少?可能是该类型的一些默认“空”实例。在这种情况下,不太可能使调试更加困难,因为应该赋值的值没有。只是有一些默认行为而不是引起异常并不像我想要的那样。

答案 2 :(得分:3)

我认为非可空引用类型的概念对于映射到数据库字段的ORM生成的属性非常有用。通常,您无法从属性(通常是类型字符串)判断底层字段是否可为空。只需查找问号,您就可以使用可为空的值类型。

我不太担心静态检查,除了明显的foo! = null;我认为,失败,但智能感知作为变量意图的暗示非常有用。

答案 3 :(得分:0)

  

编译时不可空的引用检查是我在代码契约中等待的杀手级功能,它实际上并不存在。

2017年更新(8年后),而非可空引用类型仍然不存在...可以为空的引用类型。

Mads Torgersen(Microsoft的C#语言PM)确实提到它in this tweet

  

可以为空的引用类型的原型终于来了!

详情请参阅“Introducing Nullable Reference Types in C#”,并在此视频“new features available C# 7.1 and 7.2”中详细说明。

  

如果我们只添加一种新的“安全”类型的引用类型,然后将现有引用类型重新解释为另一种“安全”类型,则可以实现这一点。更具体地说,我们认为未注释的引用类型(如string)的默认含义应该是不可为空的引用类型,原因如下:

     

我们认为要求引用不为null更为常见。可以为空的引用类型(虽然我们没有好的数据告诉我们多少),所以它们应该需要一个新的注释。   该语言已经具有 - 可空值类型的概念 - 和语法。两者之间的类比将使语言添加在概念上更容易,并且在语言上更简单   你不应该为自己或你的消费者增加繁琐的空值,除非你已经主动决定你想要它们,这似乎是正确的。缺乏,而不是缺少它们,应该是你明确要选择的东西   这是它的样子:

class Person
{
    public string FirstName;   // Not null
    public string? MiddleName; // May be null
    public string LastName;    // Not null
}
  

这个类现在能够表达每个人都有名字和姓氏的意图,但只有一些人有中间名。

     

因此,我们得出我们称这种语言特征为“可空引用类型”的原因:那些是被添加到语言中的那些。不可废的那些已经存在,至少在语法上。

这仍然是原型,可能会以语言结束(或不是) 请点击“The C# Nullable Reference Types Preview”了解更多信息。

答案 4 :(得分:-2)

而不是使用null,你可以使用像string.empty这样的默认值,不需要nulls