我有一个像这样的 struct
(为简洁起见进行了简化):
public struct Period
{
public DateTime? Start { get; private set; }
public DateTime? End { get; private set; }
public bool IsMoment
{
get { return this.Start.HasValue && this.Start == this.End; }
}
public Period(DateTime? start, DateTime? end) : this()
{
this.Start = start;
this.End = end;
}
public override string ToString()
{
return this.IsMoment
? this.Start.Value.ToString("g")
: string.Format("{0:g} – {1:g}", this.Start, this.End);
}
}
一切正常,但 ReSharper 在 this.Start.Value.ToString
上显示警告:
Possible '
System.InvalidOperationException
'
如果我将 IsMoment
属性的主体复制到条件中,警告就会消失,但我希望能够重用该属性。我可以通过注释禁用 ReSharper 警告(这是我目前所做的),或者通过将 ToString
更改为 string.Format
,但我有一些在我的代码中的其他地方,这让我开始思考。我会尝试使用 code contracts 来解决这个问题,但不幸的是,我在代码契约方面没有太多经验,我不确定它会是什么样子。
我是否使用代码契约向 ReSharper 表明如果 IsMoment
为 true
,则 Start
不是 null
?
最佳答案
在 IsMoment 中做这样的事情:
contract.ensures(result == false || start <> 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);
}
这看起来像是一些不必要的工作,看起来效率低下,但更“正确”。但是,如果您的结构很小,那么在很多情况下这实际上可能更有效。
关于c# - 在一个属性中使用代码契约来提供关于另一个属性的提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24455859/