c# - 在一个属性中使用代码契约来提供关于另一个属性的提示

标签 c# .net visual-studio-2012 resharper code-contracts

我有一个像这样的 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 表明如果 IsMomenttrue,则 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/

相关文章:

c# - 使用带有 XML 配置的 Autofac

c# - 如何在 C# 中存储从 C++ 函数返回的 uint8_t* 变量?

c# - 我的 c# bin 文件夹中的 vshost 文件是什么?

c# - 在哪里停止使用 async/await 关键字?

c++ - Visual Studio 2012 : “Apply Code Changes” is disabled C++

c# - NLog在C#中获取消息

C# IL - 调用构造函数

c# - 按 ID 的 BinarySearch 对象数组

c++ - 有条件地跳过 dll 依赖项

c++ - GLOG 只保存一个文件,第一条消息