我正在使用代码合同(实际上,使用此方法学习)。
我面临一些奇怪的事情......我重写了一个在第三方程序集中定义的方法。我想添加一个Contract.Require
语句,如下所示:
public class MyClass: MyParentClass
{
protected override void DoIt(MyParameter param)
{
Contract.Requires<ArgumentNullException>(param != null);
this.ExecuteMyTask(param.Something);
}
protected void ExecuteMyTask(MyParameter param)
{
Contract.Requires<ArgumentNullException>(param != null);
/* body of the method */
}
}
但是,我收到这样的警告:
警告1 CodeContracts: 方法'MyClass.DoIt(MyParameter)'覆盖'MyParentClass.DoIt(MyParameter))',因此无法添加Requires。
[edit] 稍微更改了代码以显示替代问题 [/ edit]
如果我删除了DoIt方法中的Contract.Requires
,我会收到另一个警告,告诉我必须提供未经证实的param != null
我不明白这个警告。原因是什么,我可以解决吗?
答案 0 :(得分:14)
您无法添加呼叫者可能不知道的额外要求。它违反了Liskov's Subtitution Principle。多态性的一点是,调用者应该能够处理实际引用派生类的实例的引用,就好像它引用了基类的实例一样。
考虑:
MyParentClass foo = GetParentClassFromSomewhere();
DoIt(null);
如果这是静态地确定有效,那么你的派生类举起手并说“不!你不打算用空参数调用DoIt
是错误的!”合同的静态分析的目的是你可以在编译时确定调用,逻辑等的有效性......所以在执行时不能添加额外的限制,这是由于多态性而发生的。
派生类可以添加对它将要执行的操作的保证 - 它将确保什么 - 但它不能再为调用者提供需求以用于重写方法。
答案 1 :(得分:1)