C# 在一个属性中使用代码契约提供关于另一个属性的提示
我有一个这样的C# 在一个属性中使用代码契约提供关于另一个属性的提示,c#,.net,visual-studio-2012,resharper,code-contracts,C#,.net,Visual Studio 2012,Resharper,Code Contracts,我有一个这样的struct(为简洁起见简化): 一切正常,但ReSharper在this.Start.Value.ToString上显示警告: 可能的'系统。无效操作异常'/code>' 如果我将IsMoment属性的主体复制到条件中,警告就会消失,但我希望能够重用该属性。我可以通过注释禁用ReSharper警告(这是我目前所做的),或者通过将ToString更改为string.Format,但我的代码中还有一些类似的地方,这让我开始思考。我会尝试使用来解决这个问题,但不幸的是,我对代码契约没有
struct
(为简洁起见简化):
一切正常,但ReSharper在this.Start.Value.ToString上显示警告:
可能的'系统。无效操作异常'/code>'
如果我将IsMoment
属性的主体复制到条件中,警告就会消失,但我希望能够重用该属性。我可以通过注释禁用ReSharper警告(这是我目前所做的),或者通过将ToString
更改为string.Format
,但我的代码中还有一些类似的地方,这让我开始思考。我会尝试使用来解决这个问题,但不幸的是,我对代码契约没有太多的经验,我不确定它会是什么样子
我是否使用代码契约向ReSharper指出,如果IsMoment
为true
,则Start
不是null
?是否尝试过将参数包装在它周围
public override string ToString()
{
return (this.IsMoment
? this.Start.Value.ToString("g")
: string.Format("{0:g} – {1:g}", this.Start, this.End));
}
这可能是使用契约的情况。假设
public override string ToString()
{
if (this.IsMoment) {
Contract.Assume(this.Start.HasValue);
return this.Start.Value.ToString("g");
}
else
return string.Format("{0:g} – {1:g}", this.Start, this.End));
}
在IsMoment中执行以下操作:
确保(结果==false | |开始为null)
(这不完全正确。我正在手机上输入。)
更新:
问题可能是由于多线程代码可能会在IsMoment测试和Start.value求值之间更改Start的值
将值复制到其他线程无法修改的局部变量中可能更为正确
public override string ToString()
{
Period local = this;
return local.IsMoment
? local.Start.Value.ToString("g")
: string.Format("{0:g} – {1:g}", local.Start, local.End);
}
这看起来像是一些不必要的工作,可能看起来效率低下,但它更“正确”。但是,如果您的结构很小,在许多情况下,这实际上可能会更有效。我尝试过这个方法,但它并没有改变行为。我还尝试了一些其他形式,包括将?:
更改为if
/else
。谢谢,这确实解决了错误,但我必须将其复制到我调用IsMoment
的每个地方。我希望通过IsMoment
中的合同来实现这一点。这个想法看起来很有希望。我尝试了Contract.confirures(!Contract.Result()| this.Start.HasValue)
和其他几个变体。不幸的是,它们似乎都不起作用。重新竖琴的警告仍然存在。我将继续接受这个答案。它似乎使静态合同检查程序感到高兴,但不会使其重新精简。我猜ReSharper的检查器不够复杂,无法检查在其他属性或方法中定义的契约(至少在本例中不是这样)。最后,我将它改为this.Start.GetValueOrDefault().ToString(“g”)
,这满足了ReSharper的要求,我认为它甚至可以稍微更有效地绕过null
的HasValue
检查。
public override string ToString()
{
Period local = this;
return local.IsMoment
? local.Start.Value.ToString("g")
: string.Format("{0:g} – {1:g}", local.Start, local.End);
}