【问题标题】:Issue with Code Contracts on Generic Interface通用接口上的代码合同问题
【发布时间】:2012-02-01 19:36:00
【问题描述】:

我遇到了涉及通用接口合同的问题。我有两个通用接口,每个接口都有一个方法,它有一个前提条件(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 pointed out,正在编写合同(通过 IL 确认),因此这似乎特定于代码合同编辑器扩展。

【问题讨论】:

    标签: c# .net generics interface code-contracts


    【解决方案1】:

    我无法复制这个。鉴于此代码(以及您的示例):

    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;
        }
    }
    

    合约按预期传播(通过反射器反编译):

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

    【讨论】:

    • 你说得对,它确实出现在 IL 中;我没有检查。您是否安装了代码合同编辑器扩展?我很想知道合同装饰是否会出现在你面前。
    • Parse 没有显示任何内容。但是,当我将鼠标悬停在Export 上时,它会显示“此成员没有合同”,这很奇怪。可能与最新的 CC 版本有些不兼容?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 2011-01-26
    • 2013-01-23
    • 2012-09-01
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多