带有可选方法的 C# 接口

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2379544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:56:04  来源:igfitidea点击:

C# Interfaces with optional methods

c#interfaceversioning

提问by Nelson Rothermel

I understand that interfaces are contracts and any changes (even additions) break any dependent code. However, I could have sworn I read something a while back that one of the recent .NET versions (3, 3.5??) added a new attribute that could be applied to new interface members. This attribute allowed versioning and/or making members optional. It would have been something like:

我知道接口是契约,任何更改(甚至添加)都会破坏任何依赖代码。但是,我可以发誓我在不久前读到过一些最新的 .NET 版本(3、3.5??)添加了一个可以应用于新界面成员的新属性。此属性允许版本控制和/或使成员可选。它会是这样的:

interface ITest
{
    void MethodOne();

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

I have looked high and low for this but just can't seem to find it. I am wondering whether I simply misunderstood whatever I think I read and there is no such thing. Does someone have any insight?

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

采纳答案by Lasse V. Karlsen

You should create two interfaces:

您应该创建两个接口:

interface ITest
{
    void MethodOne();
}

interface ITest2 : ITest
{
    void MethodTwo();
}

This would also make it clear which functionality requires which version of your interfaces, so that you don't have to check whether the class implementing the interface is implementing just one, or both, methods.

这也将明确哪些功能需要哪个版本的接口,这样您就不必检查实现接口的类是否只实现了一种方法,或两种方法。

回答by David Morton

I know of no such attribute that allows an interface implementation to be partially implemented. You could work around this using an abstract class, however:

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

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

This would allow the user to decide whether or not they want to override MethodTwo when inheriting from Test, while forcing the overriding of MethodOne.

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

回答by Jorge Córdoba

There's no such attribute in the .NET framework.

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

回答by Kilhoffer

I've not seen such an attribute, but I guess it's possible. This articleon MSDN describes versioning through the use of the overridesand newkeywords.

我没有见过这样的属性,但我想这是可能的。MSDN 上的这篇文章通过使用overridesnew关键字描述了版本控制。

In short, C# is equipped with language features that allow derived classes to evolve and still maintain compatibility. This example shows a purely base-to-derived relationship, but the base would actually implement the interface you need to version. Having one interface require another (previous version) interface coupled with this method is quite useful as well.

简而言之,C# 配备了允许派生类发展并仍然保持兼容性的语言特性。这个例子展示了一个纯粹的基类到派生类的关系,但基类实际上会实现你需要版本化的接口。一个接口需要另一个(先前版本)接口与此方法相结合也非常有用。

Example of creating an interface that requires another:

创建需要另一个接口的示例:

public interface IMyInterface
{
  void FirstMethod();
}

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

Example of using inheritance to maintain compatibility:

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

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());
   }
}

回答by Sebastian Mach

I recently was in the situation where the dictated lack of multiple inheritance forbid me to transform an existing interface into an abstract class, and found myself with an extending solution:

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

    interface IFoo {
            int RowCount();
    }

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

That way you can provide a default version in case your abstractmethod can be defined in terms of the other functions.

这样你就可以提供一个默认版本,以防你的抽象方法可以根据其他函数来定义。

回答by Pratik Deoghare

You might have read something like

你可能读过类似的东西

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

But I don't think that could make implementation of MethodTwooptional.

但我不认为这可以使实现MethodTwo可选。

EDIT:

编辑:

I just found out by running the code that it really doesn't make implementation of MethodTwooptional.

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

回答by Eric Lippert

Are you perhaps thinking of the new "no pia" feature in C# 4? That is, we allow you to "link in" only the portions of an interface you actually use from a PIA, and then you can skip shipping the PIA to your customers. If you then do this several times in several different assemblies, the CLR does the work of figuring out that all those linked-in partial interfaces are logically the same type, and unifies them. That way you can pass objects that implement each flavour of the interface from one assembly to another and it all just works. However, the originalinterfaces that the "no pia" interfaces are created from has to be the same.

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

回答by Leon Lucardie

Update for 2019:If your project supports C# 8.0 you can use "default interface implementations", which makes the method optional to implement and fall back on the default implementation if you choose not to implement it.

2019 年更新:如果您的项目支持 C# 8.0,您可以使用“默认接口实现”,这使得该方法可选择实现,如果您选择不实现它,则回退到默认实现。

interface ITest
{
    void MethodOne();

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