通用接口上的代码契约问题

本文关键字:代码 契约 问题 接口 | 更新日期: 2023-09-27 18:22:05

我遇到一个涉及通用接口合同的问题。我有两个通用接口,每个接口都有一个方法,该方法有一个前提条件(Requires契约)。第一个接口的约定按预期工作:先决条件被传播到实现类,接口方法被适当地修饰(通过代码约定编辑器扩展)。未检测到第二个接口的约定,但两个接口/约定对之间的代码几乎相同。

//
// Example working as expected
//
[ContractClass(typeof(IExporterContract<>))]
public interface IExporter<in TInput> 
    where TInput : class
{
    // Shows adornment "requires obj != null"; contracts propogate
    void Export(TInput obj);
}
[ContractClassFor(typeof(IExporter<>))]
abstract class IExporterContract<TInput> : IExporter<TInput>
    where TInput : class
{
    public void Export(TInput obj)
    {
        Contract.Requires(obj != null);
    }
}

// 
// Example with unexpected behavior
//
[ContractClass(typeof(IParserContract<>))]
public interface IParser<out TOutput>
    where TOutput : class
{
    // Workbook is Microsoft.Office.Interop.Excel.Workbook
    // Does not show adornment "requires workbook != null"; contracts do not propogate
    TOutput Parse(Workbook workbook);
}
[ContractClassFor(typeof(IParser<>))]
abstract class IParserContract<TOutput> : IParser<TOutput>
    where TOutput : class
{
    public TOutput Parse(Workbook workbook)
    {
        Contract.Requires(workbook != null);
        return default(TOutput);
    }
}  

值得注意的是,Microsoft.Office.Interop.*中的任何接口都会导致这种行为。使用任何其他类型,一切都可以按预期进行。然而,我不知道为什么会这样。

编辑:正如Porges所指出的,合同正在编写中(通过IL确认),因此这似乎是代码合同编辑器扩展所特有的。

通用接口上的代码契约问题

我无法复制它。给定此代码(以及您的示例):

class Program
{
    static void Main(string[] args)
    {
        var g = new Bar();
        g.Parse(null);
        var f = new Foo();
        f.Export(null);
    }
}
public class Foo : IExporter<Foo>
{
    public void Export(Foo obj)
    {
    }
}
public class Bar : IParser<Bar>
{
    public Bar Parse(Workbook workbook)
    {
        return null;
    }
}

合同按预期传播(通过Reflector反编译):

public Bar Parse(Workbook workbook)
{
    __ContractsRuntime.Requires(workbook != null, null, "workbook != null");
    return null;
}