Dan*_*rth 9 .net c# code-contracts
假设以下代码:
[ContractClass(typeof(ICC4Contract))]
public interface ICC4
{
bool IsFooSet { get; }
string Foo { get; }
}
public class CC4 : ICC4
{
private string _foo;
public bool IsFooSet { get { return Foo != null; } }
public string Foo { get { return _foo; } }
}
[ContractClassFor(typeof(ICC4))]
public abstract class ICC4Contract : ICC4
{
public bool IsFooSet
{
get
{
Contract.Ensures((Contract.Result<bool>() && Foo != null)
|| !Contract.Result<bool>());
return false;
}
}
public string Foo
{
get
{
Contract.Ensures((Contract.Result<string>() != null && IsFooSet)
|| !IsFooSet);
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
合同试图说:
IsFooSettrue如果Foo不是,将返回null.Foonull如果IsFooSet退货则不返回true.这几乎可行.
但是,我得到一个"确保未经证实" return _foo;,因为检查器没有意识到Foo总是相等_foo.
Foo使用privatesetter 更改为自动属性会删除该警告,但我不想这样做(我不喜欢使用私有setter的自动属性).
在保留_foo字段时,我需要更改上述代码以使警告消失?
以下不起作用:
IsFooSet使用_foo代替Foo.这将导致额外的"确保未经证实" IsFooSet.Foo == _foo.这将导致隐式默认构造函数的"不变未经证实".此外,在真实的代码库上,静态检查器的处理时间将更高.Contract.Ensures(Contract.Result<string>() == _foo);到getter 不会改变任何东西.Foo您可以使用短路来简化条件,这出于某种原因是有效的:
[ContractClassFor(typeof(ICC4))]
public abstract class ICC4Contract : ICC4
{
public bool IsFooSet
{
get
{
Contract.Ensures(!Contract.Result<bool>() || Foo != null);
return false;
}
}
public string Foo
{
get
{
Contract.Ensures(!IsFooSet || Contract.Result<string>() != null);
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud)