这可能主要是一个样式问题,但是在定义非界面界面成员的代码合同时,哪种方法是最好的:
接口:
[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
合同方法;它不是要被称为。因此,我更喜欢InvalidOperationException
或NotSupportedException
。
(您甚至可以投掷自定义异常类型,例如 NotMeantToBeCalledException
。)
这应该是一个完全主观的(和学术)论点,因为ContractClassFor
类中的代码永远都不应被调用。:-)。当您暗示(通过non-void
)时,exception
或default
路线仅是班级需要编译的,并且与方法中包含的合同无关。
显然,抽象类不能直接实例化,但是,您应该将ContractClassFor
类的可见性降低到internal
,以减少其意外分类的更改。
此外,乔恩气管进一步走得更远,并添加了一个无参数的构造函数,以防止任何实例化的机会:
private IFooContract() { }
(并间接回答您的问题,通过进一步表达这是一个"特殊"合同,围绕着合同无法直接放置在界面中的事实,您的代码读者将很容易识别它就是这样忽略default
/exception
编译器安慰剂)