实现非空隙接口代码合同 - 默认(t)与投掷NotimplementException



这可能主要是一个样式问题,但是在定义非界面界面成员的代码合同时,哪种方法是最好的:

接口:

[ContractClass(typeof(IFooContract))]
public interface IFoo
{
    object Bar();
}

合同选项1:

[ContractClassFor(typeof(IFoo))]
public abstract class IFooContract : IFoo
{
    object IFoo.Bar()
    {
        Contract.Ensures(Contract.Result<object>() != null);
        throw new NotImplementedException();
    }
}

合同选项2:

[ContractClassFor(typeof(IFoo))]
public abstract class IFooContract : IFoo
{
    object IFoo.Bar()
    {
        Contract.Ensures(Contract.Result<object>() != null);
        return default(T);
    }
}

我所看到的大多数文献都倾向于选项2,但我觉得选项1更好,因为这纯粹是关于合同的(并且在从技术上讲,选项2都打破了刚刚定义的合同)。

是否有任何方案优先于选项1?

抛出异常在语义上更正确,因为不再以看似合理的方式调用和使用合同类;呼叫者将被停止并告知他们的错误。

但是, NotImplementedException似乎并不是要投掷的适当例外:该例外通常标志着尚未实现的代码(例如方法主体)的一部分。但是已实施了非void合同方法;它不是要被称为。因此,我更喜欢InvalidOperationExceptionNotSupportedException

(您甚至可以投掷自定义异常类型,例如 NotMeantToBeCalledException。)

这应该是一个完全主观的(和学术)论点,因为ContractClassFor类中的代码永远都不应被调用。:-)。当您暗示(通过non-void)时,exceptiondefault路线仅是班级需要编译的,并且与方法中包含的合同无关。

显然,抽象类不能直接实例化,但是,您应该将ContractClassFor类的可见性降低到internal,以减少其意外分类的更改。

此外,乔恩气管进一步走得更远,并添加了一个无参数的构造函数,以防止任何实例化的机会:

private IFooContract() { }

(并间接回答您的问题,通过进一步表达这是一个"特殊"合同,围绕着合同无法直接放置在界面中的事实,您的代码读者将很容易识别它就是这样忽略default/exception编译器安慰剂)