我正在一个大型项目上工作,即使有成千上万个自动化测试和100%的代码覆盖率,我们仍然会遇到大量错误。我们大约95%的错误都是NullReferenceExceptions。
有没有办法在编译时强制执行空值检查?
如果不能实现,是否有任何自动化方法可以在单元测试中强制执行空值检查而无需手动编写这些测试?
我正在一个大型项目上工作,即使有成千上万个自动化测试和100%的代码覆盖率,我们仍然会遇到大量错误。我们大约95%的错误都是NullReferenceExceptions。
有没有办法在编译时强制执行空值检查?
如果不能实现,是否有任何自动化方法可以在单元测试中强制执行空值检查而无需手动编写这些测试?
<plug>
你还可以免费阅读C# in Depth第二版的代码契约章节预发布版本 - 下载第15章</plug>
。(与最新版本的代码契约相比,该章节略有过时,但没有太大影响。)<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
string
和 string?
NonNullableClass
和 NullableClass?
百分之百的代码覆盖率毫无意义。
这是一种虚假的安全感。
你所衡量的唯一指标就是你执行了所有的代码行。
而不是:
例如,如果你处理火灾的程序只有一个步骤“逃离大楼”,即使在100%的情况下都这样做,也许一个更好的程序是“通知消防部门,尝试扑灭火势,然后如果万一全部失败再逃离”。
如果没有特别添加代码,C# 中没有任何内置的功能可以帮助你解决这个问题,你需要使用代码合同(.NET 4.0)或特定的 IF 语句(<4.0)。
public class Customer
{
public List<Order> Orders {get;set;}
}
//now to use it
Customer c = new Customer;
Order o = c.Orders.First(); //oops, null ref exception;
1) 我认为Resharper可以建议您检查代码中的一些关键位置。例如,它建议添加[空引用检查代码]并在您允许的情况下添加。
试试吧。当然,如果需要的话,它会增加您的经验。
2) 在应用程序开发的早期阶段,在您的代码中使用“快速失败”模式(或断言)。
防御式编程只能带你走到这里,也许最好的方法是捕获异常并像处理其他异常一样处理它。
ArgumentNullException
,已记录并忽略)。 - John Saunders.NET框架希望通过使用!修饰符来强制执行编译时空引用检查。
public void MyMethod(!string cannotBeNull)
但不幸的是,我们没有编译时检查。您最好的选择是尽量减少外部调用者传递空值的次数,然后在公共方法中执行空检查:
public class ExternalFacing
{
public void MyMethod(string arg)
{
if (String.IsNullOrEmpty(arg))
throw new ArgumentNullException(arg);
implementationDependency.DoSomething(arg);
}
}
internal class InternalClass
{
public void DoSomething(string arg)
{
// shouldn't have to enforce null here.
}
}
然后对外部类应用适当的单元测试,以期望ArgumentNullExceptions异常。
C# 3 不支持这两种情况,您需要使用类似 Spec# 的东西... 我想 C# 4 可能已经将一些内容集成到其中,但我对此不确定。
Spec#: http://research.microsoft.com/en-us/projects/specsharp
在编译时,您无法进行空值检查,因为在编译时对象仅是类型,并且仅在运行时将类型转换为具有实际值的实例...这里是 null。
{} = null
和return null;
?如果您从未将任何东西设置为null,则唯一需要检查null的是库调用的结果。 - Anon.