是否可以使用可选的实现方法定义接口?例如,我的核心库中有以下接口定义作为IDataReader:
public interface IDataReader<T> {
void StartRead(T data);
void Stop();
}
但是,在我当前的实现中,从未使用或实现过Stop()方法。在我的所有实现类中,必须使用throw NotImplementedExcetion()作为默认值来实现此方法:
class MyDataReader : IDataReader<MyData> {
...
public void Stop()
{
// this none implementaion looks like uncompleted codes
throw NotImplementedException();
}
当然,我可以删除throw异常代码并将其留空。
当我设计这个数据阅读器界面时,我认为应该提供一种方法来停止阅读过程。也许我们将来某个时候会使用Stop()。
无论如何,不确定是否可以将此Stop()方法作为可选的实现方法?我能想到的唯一方法是要么定义两个接口,一个是stop,另一个是没有IDataReader和IDataReader2。另一个选择是将这个打破到这样的接口:
interface IDataReader<T> {
void StartRead(T data);
}
interface IStop {
void Stop();
}
在我的实现案例中,我必须转换或使用IStop来检查我的实现是否支持Stop()方法:
reader.StartRead(myData);
....
// some where when I need to stop reader
IStop stoppable = reader as IStop;
if (stoppable != null ) stoppable.Stop();
...
我仍然需要编写这些代码。有什么建议?不确定是否有任何方法可以在.Net或C#中的接口中定义可选的实现方法?
答案 0 :(得分:7)
有趣。我必须在这里引用你的话:
然而,在我目前 实现,Stop()方法有 从未使用或实施过。在所有 我的实现类,这个方法 必须用throw实现 默认情况下NotImplementedExcetion():
如果是这种情况,那么您有两个选择:
更新我认为方法可选的唯一方法是将方法分配给变量(类似于方法签名的委托类型),然后在尝试之前评估方法是否为null在任何地方都可以打电话。
这通常是针对事件处理程序完成的,其中处理程序可能存在也可能不存在,并且可以视为可选。
答案 1 :(得分:6)
有关信息,在BCL中相当常见的另一种方法是在同一界面上Supports*
,即
bool SupportsStop {get;}
void Stop();
(例如,在IBindingList
中)。
我不是假装它是“纯粹的”或任何东西,但它有效 - 但这意味着你现在有两个方法来实现每个功能,而不是一个。单独的接口(例如IStoppableReader
)可能更好。
有关信息,如果实现在所有实现之间很常见,那么您可以使用扩展方法;一个简单的例子:
public static void AddRange<T>(this IList<T> list, IEnumerable<T> items) {
foreach(T item in items) list.Add(item);
}
(或您的界面的等效物)。如果您针对具体类型提供更专业的版本,那么它将优先(但仅当调用者知道变量为具体类型,而不是接口时)。因此,如上所述,任何人故意使用List<T>
仍然使用List<T>
的{{1}}版本;但如果有一个AddRange
但只知道它为List<T>
,它将使用扩展方法。
答案 2 :(得分:5)
如果该方法不适合您的实现,请抛出InvalidOperationException
,就像大多数迭代器在它们上面调用Reset
时一样。另一种选择是NotSupportedException
,System.IO
倾向于使用Stop
。后者更符合逻辑(因为它与对象的当前状态无关,只与其具体类型有关),但前者在我的经验中更常用。
但是,最好只在实际需要时将内容放入界面中 - 如果您仍处于可以删除{{1}}的位置,如果我是你,我会这样做。
对语言或CLR中的可选接口成员没有统一支持。
答案 3 :(得分:4)
如果您的代码中没有类实际实现Stop()
,并且您将来没有明确计划这样做,那么您在界面中不需要它。否则,如果某些但所有的对象都是“可停止”的,那么正确的方法确实是使其成为一个单独的界面,例如IStoppable
,然后客户端应该根据需要查询它。
答案 4 :(得分:0)
如果您的实现没有实现接口方法Stop,那么它会明显破坏您的接口附带的合同。您可以适当地实现Stop方法(不是通过抛出异常而不是将其留空)或者您需要重新设计界面(以便更改合同)。
最好的问候
答案 5 :(得分:0)
C#第4版(or vNext)正在考虑default implementation for interfaces - 几个月前我在channel9听到了这个消息;)。
具有默认实现的接口的行为有点像抽象基类。现在您可以继承多个接口,这可能意味着C#可能会以默认实现的接口形式获得多重继承。
在此之前,您可能会使用扩展方法......
或者你的类型可以使用代表。
interface IOptionalStop
{
Action Stop { get; }
}
public class WithStop : IOptionalStop
{
#region IOptionalStop Members
public Action Stop
{
get;
private set;
}
#endregion
public WithStop()
{
this.Stop =
delegate
{
// we are going to stop, honest!
};
}
}
public class WithoutStop : IOptionalStop
{
#region IOptionalStop Members
public Action Stop
{
get;
private set;
}
#endregion
}
public class Program
{
public static string Text { get; set; }
public static void Main(string[] args)
{
var a = new WithStop();
a.Stop();
var o = new WithoutStop();
// Stop is null and we cannot actually call it
a.Stop();
}
}