C#与可选方法的接口

时间:2010-03-04 13:26:51

标签: c# interface versioning

我理解接口是契约,任何更改(甚至添加)都会破坏任何相关代码。但是,我可以发誓我曾经读过一些最近的.NET版本(3,3.5 ??)添加了一个可以应用于新接口成员的新属性。此属性允许版本控制和/或使成员可选。它应该是这样的:

interface ITest
{
    void MethodOne();

    [InterfaceVersion(2)]
    void MethodTwo();
}

我为此寻找高低,但似乎无法找到它。我想知道我是否只是误解了我认为我读过的东西而且没有这样的东西。有人有任何见解吗?

8 个答案:

答案 0 :(得分:45)

您应该创建两个接口:

interface ITest
{
    void MethodOne();
}

interface ITest2 : ITest
{
    void MethodTwo();
}

这也可以清楚地说明哪个功能需要哪个版本的接口,这样您就不必检查实现接口的类是否只实现一个或两个方法。

答案 1 :(得分:10)

我没有看到这样的属性,但我想这是可能的。 MSDN上的This article通过使用overridesnew关键字来描述版本控制。

简而言之,C#配备了语言功能,允许派生类进化并仍然保持兼容性。此示例显示了纯粹的基于派生的关系,但基本实际上将实现版本所需的接口。 有一个界面需要另一个(以前的版本)接口加上这种方法也非常有用。

创建需要另一个的界面的示例:

public interface IMyInterface
{
  void FirstMethod();
}

public interface IMySecondInterface : IMyInterface
{
  void SecondMethod();
}

使用继承来保持兼容性的示例:

public class MyBase 
{
   public virtual string Meth1() 
   {
      return "MyBase-Meth1";
   }
   public virtual string Meth2() 
   {
      return "MyBase-Meth2";
   }
   public virtual string Meth3() 
   {
      return "MyBase-Meth3";
   }
}

class MyDerived : MyBase 
{
   // Overrides the virtual method Meth1 using the override keyword:
   public override string Meth1() 
   {
      return "MyDerived-Meth1";
   }
   // Explicitly hide the virtual method Meth2 using the new
   // keyword:
   public new string Meth2() 
   {
      return "MyDerived-Meth2";
   }
   // Because no keyword is specified in the following declaration
   // a warning will be issued to alert the programmer that 
   // the method hides the inherited member MyBase.Meth3():
   public string Meth3() 
   {
      return "MyDerived-Meth3";
   }

   public static void Main() 
   {
      MyDerived mD = new MyDerived();
      MyBase mB = (MyBase) mD;

      System.Console.WriteLine(mB.Meth1());
      System.Console.WriteLine(mB.Meth2());
      System.Console.WriteLine(mB.Meth3());
   }
}

答案 2 :(得分:6)

您是否正在考虑C#4中新的“无pia”功能?也就是说,我们允许您仅从PIA“链接”实际使用的界面部分,然后您可以跳过向您的客户发送PIA。如果您在几个不同的程序集中多次执行此操作,CLR会确定所有这些链接的部分接口在逻辑上是相同的类型,并统一它们。这样,您可以将实现接口的每种风格的对象从一个程序集传递到另一个程序集,这一切都可以正常工作。但是,创建“no pia”接口的原始接口必须相同。

答案 3 :(得分:5)

.NET框架中没有这样的属性。

答案 4 :(得分:4)

我知道没有允许部分实现接口实现的此类属性。但是,你可以使用抽象类来解决这个问题:

public abstract class Test
{
     public abstract void MethodOne();
     public virtual void MethodTwo() { }
}

这将允许用户在继承Test时强制他们是否要覆盖MethodTwo,同时强制覆盖MethodOne。

答案 5 :(得分:2)

我最近遇到了缺乏多重继承的情况,禁止我将现有接口转换为抽象类,并发现自己有一个扩展解决方案:

    interface IFoo {
            int RowCount();
    }

    static class _FooExtensions {
            public static bool HasAnyRows (this IFoo foo) {
                    return foo.RowCount() > 0;
            }
    }

通过这种方式,您可以提供默认版本,以防您的抽象方法可以根据其他功能进行定义。

答案 6 :(得分:1)

您可能已经阅读了类似

的内容
 interface ITest
{
    void MethodOne();

    [InterfaceVersion(2)]
    void MethodTwo();
}



[AttributeUsage(AttributeTargets.All)]
public class InterfaceVersion : System.Attribute
{
    public readonly int N;

    public InterfaceVersion(int n) 
    {
        this.N = n;
    }
}

但我认为这不会使MethodTwo的实施成为可选。

修改

我刚刚通过运行代码发现它实际上没有使MethodTwo的实现可选。

答案 7 :(得分:1)

2019年更新:如果您的项目支持C#8.0,则可以使用“ default interface implementations ”,这使该方法成为可选的实现方式,并依赖于如果您选择不实施,则为默认实施。

interface ITest
{
    void MethodOne();

    public void MethodTwo()
    {
       //Empty default implementation
    }
}