C# 沿着继承链重复代码契约要求?

C# 沿着继承链重复代码契约要求?,c#,.net-4.0,code-contracts,C#,.net 4.0,Code Contracts,假设您有一个现有的大型项目,并且希望在其中集成代码契约。现有代码使用if null,然后抛出逻辑。对于给定的条件,文档建议将组装模式设置为自定义参数验证 我有以下课程: class A { protected virtual void Foo(int a, int b) { if (a == null) throw new ArgumentNullException(a); if (b == null)

假设您有一个现有的大型项目,并且希望在其中集成代码契约。现有代码使用if null,然后抛出逻辑。对于给定的条件,文档建议将组装模式设置为自定义参数验证

我有以下课程:

class A
{
    protected virtual void Foo(int a, int b)
    {
        if (a == null)
            throw new ArgumentNullException(a);
        if (b == null)
            throw new ArgumentNullException(b);
        Contract.EndContractBlock();
    }
}
class B : A
{
    protected override void Foo (int a, int b)
    {
        // some stuff
        base.Foo(a, b);
    }
}
编译时,我得到以下警告:

警告CC1055:方法“B.Foo(int,int)”应包含自定义 “需要(a!=null)”的参数验证 因为它覆盖了“A.Foo(int,int)”,这表明它确实如此。如果你不 要在此程序集中使用自定义参数验证,请更改 “标准合同要求”的装配模式


我不想在每个重写的方法上重复前提条件!有办法解决吗?

如果您使用
Contract.Requires()
而不是
Contract.EndContractBlock()
,则效果很好

下面引用的手册中有一节建议在方法覆盖中添加
[SuppressMessage]
属性

参见第22页第5.2.3节

将检查委托给其他方法

假设您有一个类似于以下代码的代码模式:

public class Base {
    public virtual void Compute(string data) {
    if (data == null) throw new ArgumentNullException(...);
        Contract.EndContractBlock();
        ...
    }
}

public class Derived : Base {
    public override void Compute(string data) {
        base.Compute(data);
        ...
    }
}
然后,工具将发出警告CC1055,并显示以下信息:

方法“Derived.Compute”应包含的自定义参数验证 “需要(ArgumentNullException)(数据!=null)”,因为它会覆盖 “Base.Compute”表明它确实如此

在这种情况下,警告是没有帮助的,因为 派生的。计算将参数验证委托给另一个 方法(在本例中为基本方法)。要避免出现此警告,请执行以下操作: 在不重复验证的情况下,可以添加 方法的SuppressMessage属性:

public class Derived : Base {
    [SuppressMessage("Microsoft.Contracts", "CC1055", Justification = "Validation performed in base method")]
    public override void Compute(string data) {
        base.Compute(data);
        ...
    }
}

如果您使用
Contract.Requires()
而不是
Contract.EndContractBlock()
,则可以正常工作

下面引用的手册中有一节建议在方法覆盖中添加
[SuppressMessage]
属性

参见第22页第5.2.3节

将检查委托给其他方法

假设您有一个类似于以下代码的代码模式:

public class Base {
    public virtual void Compute(string data) {
    if (data == null) throw new ArgumentNullException(...);
        Contract.EndContractBlock();
        ...
    }
}

public class Derived : Base {
    public override void Compute(string data) {
        base.Compute(data);
        ...
    }
}
然后,工具将发出警告CC1055,并显示以下信息:

方法“Derived.Compute”应包含的自定义参数验证 “需要(ArgumentNullException)(数据!=null)”,因为它会覆盖 “Base.Compute”表明它确实如此

在这种情况下,警告是没有帮助的,因为 派生的。计算将参数验证委托给另一个 方法(在本例中为基本方法)。要避免出现此警告,请执行以下操作: 在不重复验证的情况下,可以添加 方法的SuppressMessage属性:

public class Derived : Base {
    [SuppressMessage("Microsoft.Contracts", "CC1055", Justification = "Validation performed in base method")]
    public override void Compute(string data) {
        base.Compute(data);
        ...
    }
}

这是因为您在传统模式下使用它,而传统模式不会继承合同。(因为在遗留代码中,契约无论如何都应该重复。)如果您想要自动继承,应该使用
Contract.Requires
。为什么要重复?为什么cccheck不够智能,无法识别基本方法调用并自动获取合同先决条件?@RomanRoyter遗憾的是,它似乎与“手动防护”没有直接关系,需要或需要。。如果有,它会简单得多。这是因为您在传统模式下使用它,而传统模式不会继承合同。(因为在遗留代码中,契约无论如何都应该重复。)如果您想要自动继承,应该使用
Contract.Requires
。为什么要重复?为什么cccheck不够智能,无法识别基本方法调用并自动获取合同先决条件?@RomanRoyter遗憾的是,它似乎与“手动防护”没有直接关系,需要或需要。。如果有,那就简单多了。