为什么代码契约建议我需要一个参数为空?
本文关键字:一个 参数 契约 代码 为什么 | 更新日期: 2023-09-27 18:15:14
看下面的代码示例,微软代码契约警告:
CodeContracts:在极度可见的方法中缺少前提条件。考虑添加Contract。要求(科学== null);为参数验证
我错过了什么吗?为什么CC建议我要求参数为null,这与这里应该做的完全相反?
我使用的是VS2015, . net 4.6。
using System;
using System.Diagnostics.Contracts;
public sealed class Weird
{
public Weird(object science)
{
if (null == science)
{
throw new ArgumentNullException();
}
Contract.EndContractBlock();
this.Science = science;
}
private object Science { get; }
[ContractInvariantMethod]
private void ObjectInvariant()
{
Contract.Invariant(null != this.Science);
}
}
这不是一个比你的解决方案更好的答案,但我让它"工作"通过简单地改变:
private object Science { get; }
:
private object Science { get; set; }
基本上与你的变通方法相同,但没有提供你自己的支持字段。我猜Code Contracts不太理解新语法
尽量不要使用反向比较。在c#中没有必要写:
if (null == science)
代替
if (science == null)
你的代码将变得更清晰,我认为错误的合同建议将会消失。同样,如果你犯了一个错误,在if
块中只写了一个赋值(=
),编译器会警告你。
为了使你的代码更清晰,你可以尝试使用一些AOP的东西,比如PostSharp,并将你的契约指定为接口中的属性属性,你的类将实现这些属性。因此,合同逻辑将不会与业务逻辑交叉。
根据变通方法,CC似乎不理解只读auto属性在构造函数中是可写的。提供的两种解决方法都消除了向只读属性写入的操作。也许CC试图通过将执行发送到唯一可用的其他分支(null == science
)来避免执行它认为错误的语句(this.Science = science;
)。
早期版本的c#不允许写入只读auto属性。我猜代码合同系统没有收到备忘录!
我发现当我用字段支持的属性替换auto属性时,警告消失了。将以下代码与我在原始问题中发布的代码进行比较:
using System;
using System.Diagnostics.Contracts;
public sealed class Weird
{
public Weird(object science)
{
if (science == null)
{
throw new ArgumentNullException();
}
Contract.EndContractBlock();
this.science = science;
}
private readonly object science;
private object Science
{
get
{
return this.science;
}
}
[ContractInvariantMethod]
private void ObjectInvariant()
{
Contract.Invariant(null != this.Science);
}
}
我不喜欢这样,因为我不需要仅仅为了满足代码契约而使用字段支持的属性。但是,哦,好吧,我想。
我仍然开放的答案,让我满足我的合同,而使用自动属性