Code Contracts: How to deal with inherited interfaces?

不羁岁月 提交于 2019-12-06 02:03:51

问题


I'm using MS Code Contracts and have run into a snag with using interface inheritance and ContractClassFor attributes.

Given these interfaces and contract classes:

[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 { }

Let's say that IOne and ITwo are substantial interfaces. So IOneContract would have a significant amount of code in it for the necessary checks.

I don't want to duplicate all of that in ITwoContract for the IOne interfaces. I only want to add new contracts for the ITwo interfaces. Inheriting one contract class from another seems the likely way to reuse that code. Yet I get the following error:

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.

Is this a limitation in Code Contracts or am I doing it wrong? We have a lot of interface inheritance in our project and this feels like a deal breaker for Code Contracts if I can't figure out how to work around this issue.


回答1:


Instead of:

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

Just inherit the contract:

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

You only need to provide contracts on the methods which are new in ITwo. The contracts from IOneContract will be inherited automatically, and you can declare all the inherited IOne methods as abstract — in fact, you cannot provide contracts for IOne on ITwoContract, or CC will complain :)

For example, if you have this:

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

Then this implementation will say "unproven contract" on both methods, as expected:

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

    public int Thing2
    {
        get { return 0; }
    }
}


来源:https://stackoverflow.com/questions/3197797/code-contracts-how-to-deal-with-inherited-interfaces

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!