查看下面的代码示例,Microsoft Code Contracts警告:
CodeContracts:在极其可见的方法中缺少前置条件。 考虑添加Contract.Requires(science == 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);
}
}
答案 0 :(得分:4)
这不是一个比你的解决方案更好的答案,但我得到了#34; work"只需改变:
private object Science { get; }
为:
private object Science { get; set; }
基本上与您的解决方法相同,但没有提供您自己的支持字段。我猜Code Code不太了解新语法。
答案 1 :(得分:3)
尽量不要使用反向比较。在C#中,没有必要写:
if (null == science)
而不是
if (science == null)
您的代码将变得更加清晰,我认为错误的合同建议将会消失。
此外,如果您在=
块内发生错误并只编写一个赋值(if
),编译器会向您发出警告。
为了使您的代码更加清晰,您可以尝试使用一些AOP内容,例如PostSharp,并将您的契约指定为接口中的属性属性,您的类将实现这些属性。所以契约逻辑不会与业务逻辑交错。
答案 2 :(得分:2)
基于解决方法,CC看起来并不了解只读的auto属性在构造函数中是可写的。这两种解决方法都提供了删除写入只读属性的操作。也许CC试图通过将执行发送到唯一的其他可用分支(this.Science = science;
)来避免执行它认为错误的语句(null == science
)。
早期版本的C#不允许写入只读的自动属性。我猜Code Codects系统没有收到备忘录!
答案 3 :(得分:1)
当我用一个字段支持的属性替换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);
}
}
我不喜欢这个,因为我不一定只是为了满足代码合同而使用现场支持的财产。但是,噢,我猜。
我仍然愿意接受一个允许我在使用自动属性时满足合同的答案。