在Interface中定义可选的实现方法?

Dav*_*.ca 8 c# .net-3.5

是否可以使用可选的实现方法定义接口?例如,我的核心库中有以下接口定义作为IDataReader:

public interface IDataReader<T> {
  void StartRead(T data);
  void Stop();
}
Run Code Online (Sandbox Code Playgroud)

但是,在我当前的实现中,从未使用或实现过Stop()方法.在我的所有实现类中,必须使用throw NotImplementedExcetion()作为默认值来实现此方法:

class MyDataReader : IDataReader<MyData> {
   ...
   public void Stop()
   {
     // this none implementaion looks like uncompleted codes
     throw NotImplementedException();
   }
Run Code Online (Sandbox Code Playgroud)

当然,我可以删除throw异常代码并将其保留为空.

当我设计这个数据阅读器界面时,我认为它应该提供一种方法来停止阅读过程.也许我们将来某个时候会使用Stop().

无论如何,不​​确定是否可以将此Stop()方法作为可选的实现方法?我能想到的唯一方法是要么定义两个接口,一个是stop,另一个是没有IDataReader和IDataReader2.另一个选择是将这个打破到这样的接口:

 interface IDataReader<T> {
    void StartRead(T data);
 }

 interface IStop {
    void Stop();
 }
Run Code Online (Sandbox Code Playgroud)

在我的实现案例中,我必须转换或使用IStop来检查我的实现是否支持Stop()方法:

 reader.StartRead(myData);
 ....
 // some where when I need to stop reader
 IStop stoppable = reader as IStop;
 if (stoppable != null ) stoppable.Stop();
 ...
Run Code Online (Sandbox Code Playgroud)

我还是要写那些代码.有什么建议?不确定是否有任何方法可以在.Net或C#中的接口中定义可选的实现方法?

Jon*_*jap 7

有趣.我必须在这里引用你的话:

但是,在我当前的实现中,从未使用或实现过Stop()方法.在我的所有实现类中,必须使用throw NotImplementedExcetion()作为默认值来实现此方法:

如果是这种情况,那么您有两种选择:

  1. 从界面中删除Stop()方法.如果接口的每个实现者没有使用它,那么它显然不属于那里.
    • 而不是接口,将您的接口转换为抽象基类.这样就不需要覆盖空的Stop()方法,直到需要为止.

更新我认为方法可选的唯一方法是将方法分配给变量(类似于方法签名的委托类型),然后在尝试在任何地方调用它之前评估方法是否为null.

这通常是针对事件处理程序完成的,其中处理程序可以存在或不存在,并且可以被认为是可选的.


Mar*_*ell 6

有关信息,BCL中相当常见的另一种方法是Supports*在同一个界面上,即

bool SupportsStop {get;}
void Stop();
Run Code Online (Sandbox Code Playgroud)

(例如,这样的例子IBindingList).

我不是假装它是"纯粹的"或任何东西,但它有效 - 但它意味着你现在有两种方法来实现每个功能,而不是一个.单独的接口(IStoppableReader例如)可能是优选的.

有关信息,如果实现在所有实现之间是通用的,那么您可以使用扩展方法; 一个简单的例子:

public static void AddRange<T>(this IList<T> list, IEnumerable<T> items) {
    foreach(T item in items) list.Add(item);
}
Run Code Online (Sandbox Code Playgroud)

(或您的界面的等效物).如果您针对具体类型提供更专业的版本,那么它将优先(但仅当调用者知道变量作为具体类型而不是接口时).因此,如上所述,任何人都故意使用List<T>静态使用List<T>的版本AddRange; 但如果有一个List<T>但只知道它IList<T>,它将使用扩展方法.


Jon*_*eet 5

如果该方法不适合您的实现,InvalidOperationException就像大多数迭代器在调用Reset它们时那样抛出.一种替代方案NotSupportedException往往被使用System.IO.后者更符合逻辑(因为它与对象的当前状态无关,只是它的具体类型),但前者在我的经验中更常用.

但是,最好只在实际需要时将东西放入界面中 - 如果你仍处于可以删除的位置,Stop如果我是你,我会这样做.

对语言或CLR中的可选接口成员没有统一支持.

  • .NET中有System.NotSupportedException;) (3认同)