Проблема с кодовыми контрактами на универсальном интерфейсе - PullRequest
3 голосов
/ 01 февраля 2012

У меня проблема с контрактами на общий интерфейс.У меня есть два общих интерфейса, каждый с одним методом, который имеет одно предварительное условие (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.* вызывает такое поведение.Используя любой другой тип, все работает как положено.Однако я не знаю, почему это так.

РЕДАКТИРОВАТЬ: как Поргес указал , контракты пишутся (подтверждено через IL), так что это кажетсячтобы быть конкретным для расширения редактора контрактов кода.

1 Ответ

2 голосов
/ 02 февраля 2012

Я не могу повторить это.Учитывая этот код (вместе с вашим примером):

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