我一直在玩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#因没有非可空参考类型而离开的空白,此时我恐怕什么都不会。 你觉得怎么样?
答案 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
可悲的事实是,如果程序正确,大多数程序中的大多数参考变量可能是不可为空的。可空变量属于少数。但它们是默认值。
答案 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