代码之家  ›  专栏  ›  技术社区  ›  scobi

代码契约:如何处理继承的接口?

  •  6
  • scobi  · 技术社区  · 15 年前

    我使用MS代码契约,在使用接口继承和ContractClassFor属性时遇到了一个障碍。

    给定这些接口和合同类:

    [ContractClass(typeof(IOneContract))]
    interface IOne { }
    [ContractClass(typeof(ITwoContract))]
    interface ITwo : IOne { }
    
    [ContractClassFor(typeof(IOne))]
    abstract class IOneContract : IOne { }
    [ContractClassFor(typeof(ITwo))]
    abstract class ITwoContract : IOneContract, ITwo { }
    

    我不想在IOne接口的ITWO合同中重复所有这些。我只想为ITwo接口添加新合同。从另一个契约类继承一个契约类似乎是重用该代码的可能方式。但我得到以下错误:

    EXEC : warning CC1066: Class 'ITwoContract' is annotated as being the contract for the interface 'ITwo' and cannot have an explicit base class other than System.Object.
    

    这是代码契约中的限制还是我做错了?在我们的项目中我们有很多接口继承,如果我不知道如何解决这个问题,这感觉就像是代码契约的一个破坏者。

    1 回复  |  直到 15 年前
        1
  •  10
  •   porges    15 年前

    而不是:

    [ContractClassFor(typeof(ITwo))]
    abstract class ITwoContract : IOneContract, ITwo { }
    

    [ContractClassFor(typeof(ITwo))]
    abstract class ITwoContract : ITwo { }
    

    您只需要提供中新方法的契约 ITwo . 合同来自 IOneContract 将自动继承,并且您可以声明所有继承的 IOne 方法是抽象的-事实上,你 提供合同 伊奥尼 ITwoContract ,否则CC将投诉:)

    例如,如果您有:

    [ContractClass(typeof (IOneContract))]
    interface IOne
    {
        int Thing { get; }
    }
    
    [ContractClass(typeof (ITwoContract))]
    interface ITwo : IOne
    {
        int Thing2 { get; }
    }
    
    [ContractClassFor(typeof (IOne))]
    abstract class IOneContract : IOne
    {
        public int Thing
        {
            get
            {
                Contract.Ensures(Contract.Result<int>() > 0);
                return 0;
            }
        }
    }
    
    [ContractClassFor(typeof (ITwo))]
    abstract class ITwoContract : ITwo
    {
        public int Thing2
        {
            get
            {
                Contract.Ensures(Contract.Result<int>() > 0);
                return 0;
            }
        }
    
        public abstract int Thing { get; }
    }
    

    然后,这个实现将在这两种方法上显示“未经验证的合同”,正如预期的那样:

    class Two : ITwo
    {
        public int Thing
        {
            get { return 0; }
        }
    
        public int Thing2
        {
            get { return 0; }
        }
    }