我应该使用类型代码合同进行通用接口吗?

时间:2012-01-05 09:54:30

标签: c# generics interface code-contracts

我有一个数学库的通用接口,如下所示:

[ContractClass(typeof(MathsDoubleContracts))]
public interface IMaths<T>
{
    T SomeFunction(T n);
}

这使我能够创建IMaths<double>IMaths<decimal>等(虽然起初我只需要double版本)。

我想设置代码合同。目前我已经做到了这一点:

[ContractClassFor(typeof(IMaths<double>))]
public abstract class MathsDoubleContracts : IMaths<double>
{
    public double SomeFunction(double n)
    {
        // Always positive
        Contract.Ensures(0 <= Contract.Result<double>());

        return double.NaN;
    }
}

这似乎有效,但我感到非常惊讶(因为我在IMaths<double>而不是IMaths<T>指定合同。)

我想知道:

  1. 我可以在通用接口上指定多个合同类,每个类型对应我想要使用的特定类型(例如[ContractClass(typeof(MathsDoubleContracts))]上同时具有[ContractClass(typeof(MathsDecimalContracts))]IMaths<T>属性?这是明智之举吗?
  2. 我是否会更好地使用通用接口而不是(例如,从IMathsDouble开始,其中所有函数都是根据双精度定义的,添加IMathsDecimal以后)?

2 个答案:

答案 0 :(得分:1)

Q1

请你举个例子。

修改

没有。它不允许多个。参考here

AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]

注意AllowMultiple = false

Q2

是的,虽然仿制药可能会带来一些好处。你的界面不是真正的通用。我不能以IMaths<File>为例。我实际上回答了一个不同但相关的问题here

您可以添加where T : ...之类的限制,但也不会这样做,因为您只能intdouble,而您只能where T : struct这是IMaths<T>不一样的。这里的泛型仅仅是一种装饰,interface IntMaths : IMaths<int> { } 的抽象不能被原样使用(或者它可以依赖于你的代码),你需要具体的类或接口。

子界面是一个安全的选择

{{1}}

答案 1 :(得分:0)

我通过将合同应用于通用接口来实现这一点,然后在运行时推断合同类型。

我的问题是在“公共代码”程序集中定义一个基本抽象接口,它适用于IService类型的对象,然后继承我需要的类型特定的实现。

但是我不必指定特定于类型的实现,我可以简单地(通过依赖注入)在运行时确定合同和对象类型...

Code contract inheritance

我认为我的问题是让它“便携”