在一个属性中使用代码契约来提供关于另一个属性的提示
本文关键字:属性 提示 另一个 契约 一个 代码 | 更新日期: 2023-09-27 18:10:29
我有一个这样的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
上显示警告:
可能的'
System.InvalidOperationException
'
如果我将IsMoment
属性的主体复制到条件中,则警告将消失,但我希望能够重用该属性。我可以用注释禁用ReSharper警告(这就是我目前所做的),或者通过将ToString
更改为string.Format
,但是我的代码中有一些其他类似的地方,它让我思考。我试着用代码契约来解决这个问题,但不幸的是,我没有很多代码契约的经验,我不确定它会是什么样子。
是否有我使用代码合同来指示ReSharper,如果IsMoment
是true
,那么Start
不是null
?
在IsMoment:
合同。确保(result == false || start <> null);
)这并不完全正确。我正在用手机打这个
更新:这个问题可能是由于多线程代码在IsMoment测试和Start测试之间改变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);
}
这看起来像是一些不必要的工作,它可能看起来效率低下,但它更"正确"。但是,如果您的结构很小,那么在许多情况下,这实际上可能更有效。
是否尝试过在它周围包装父母?
public override string ToString()
{
return (this.IsMoment
? this.Start.Value.ToString("g")
: string.Format("{0:g} – {1:g}", this.Start, this.End));
}
这可能是使用Contract.Assume
的情况。
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));
}