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);
}