简体   繁体   English

在C#中显示继承接口实现的最佳方法是什么?

[英]What is the best way to show inherited interface implementation in C#?

Given the following interfaces: 给定以下接口:

interface IFoo
{
    void Foo();
}

interface IBar : IFoo
{
    void Bar();
}

what is the best way to indicate that a given class implements IBar ? 表示给定类实现IBar的最佳方法是什么?

Approach A: 方法A:

class Implementation : IBar { ... }

This seems simpler and cleaner but it does not indicate that Implementation implements IFoo . 这看起来更简单,更清晰,但并不表示Implementation实现了IFoo

Approach B: 方法B:

class Implementation : IBar, IFoo { ... }

This seem the most informative but is the extra information really necessary? 这似乎是最丰富的信息,但真正需要的额外信息?

The extra information isn't necessary to the compiler, but it may be helpful to the reader of your code as the reader won't have to know that IBar extends IFoo . 编译器不需要额外的信息,但它可能对您的代码的读者有所帮助,因为读者不必知道IBar扩展了IFoo An example of this in the framework would be List<T> which implements <IList<T> , ICollection<T> , and IEnumerable<T> , even though IList<T> ; 框架中的一个例子是List<T> ,它实现<IList<T>ICollection<T>IEnumerable<T> ,即使IList<T> ; extends both ICollection<T> and IEnumerable<T> . 扩展ICollection<T>IEnumerable<T>

EDIT : I think, for me at least, the primary reason that I would list both is that you ordinarily don't think of interfaces inheriting from one another. 编辑 :我认为,至少对我来说,我列出这两者的主要原因是你通常不会想到接口彼此继承。 When you derive from a class, you expect that you are inheriting behavior that may itself be inherited. 从类派生时,您希望继承本身可以继承的行为。 If you are interested, you follow the derivation up the class hierarchy. 如果您感兴趣,可以按照类层次结构进行推导。 With an interface it's more unusual that the interface would be derived and thus you'd be less likely to look and more likely to miss the connection. 使用接口时,接口的派生更加不寻常,因此您不太可能看起来并且更有可能错过连接。 Listing them both solves this problem without too much pain. 列出它们都可以解决这个问题而不会有太多痛苦。

Personally I'd go with the former. 就个人而言,我会选择前者。 With the latter, say you're in this situation where you have a bunch of derived classes: 对于后者,假设你在这种情况下你有一堆派生类:

class DerivedA : Implementation, IBar, IFoo { ... }
class DerivedB : Implementation, IBar, IFoo { ... }
class DerivedC : Implementation, IBar, IFoo { ... }
class DerivedD : Implementation, IBar, IFoo { ... }

And then your requirements for Implementation change so that it now needs to implement another interface such as IBaz (which it can do without having to affect any of the derived classes as long as it provides a non-abstract implementation) then you have two options: 然后你对Implementation的要求发生了变化,现在它需要实现另一个接口,比如IBaz (只要它提供非抽象的实现,它可以做而不必影响任何派生类),那么你有两个选择:

  1. Leave all the derived class definitions without an explicit declaration of the new interface information, in which case the class definition is now incorrect according to the standard, and potentially misleading if people expect the standard to always be followed. 保留所有派生类定义,而不显式声明新接口信息,在这种情况下,类定义现在根据标准不正确,如果人们期望始终遵循标准,则可能会产生误导。

  2. Go and find all derived classes, and all their derived classes, and fix up the declarations on them. 去查找所有派生类及其所有派生类,并修复它们的声明。 This takes time, is somewhat error prone and hard to do completely, and turns your single file change into a multi-file check-in. 这需要时间,有点容易出错并且难以完全完成,并且将您的单个文件更改为多文件签入。

Neither of these options is attractive, so I'd go with the option that doesn't put you in either situation. 这些选项都没有吸引力,所以我选择不会让你处于任何一种情况的选项。 Just declare the most derived interface. 只需声明派生最多的接口。

I'd go with A. You get to see which methods you need to implement in the class itself, and the navigation tools in the IDE will help you with the rest. 我会选择A.你可以看到你需要在类本身中实现哪些方法,IDE中的导航工具将帮助你完成剩下的工作。

B would be impossible to maintain when doing any refactoring (eg, what happens if you replace IBar or split it into 2?) 在进行任何重构时,B将无法维持(例如,如果替换IBar或将其拆分为2会发生什么?)

The fact that you've already implemented IFoo in IBar means that you don't even need to specify that your concrete implementation class implements IFoo ; 您已经在IBar实现了IFooIBar意味着您甚至不需要指定您的具体实现类实现IFoo ; the CLR could infer that, and if you use Reflector on your assembly you'd see it specify that Implementation implements both IFoo and IBar even if you use Approach A. CLR可以推断出,如果你在程序集上使用Reflector,你会看到它指定Implementation实现IFooIBar即使你使用方法A.

So Approach A it is. 所以方法A就是这样。

我认为方法A足够清楚,因为(无论如何在VS.NET中)你可以很快确定IBar实现了IFoo。

Aside from readability and the differences in VB.NET (see Kathleen Dollard's comments), there is a situation with databinding that requires (B). 除了可读性和VB.NET的差异(参见Kathleen Dollard的评论)之外,还存在数据绑定需要(B)的情况。 The details have slipped my mind (I will edit unless someone beats me to it...). 细节已经浮现在我的脑海里(我会编辑,除非有人打败我...)。

I think this is the reason the .NET Framework collections explicitly implement their derived interfaces. 我认为这是.NET Framework集合显式实现其派生接口的原因。

I would choose approach A simply because listing an interface in the list of derivations for a class definition implies that you are providing an implementation in that class. 我会选择方法A,因为在类定义的派生列表中列出一个接口意味着您在该类中提供了一个实现。 If you do not intend to provide an alternate implementation of IFoo, then I would not include it in the list, unless you need it as a simple "marker interface". 如果您不打算提供IFoo的替代实现,那么我不会将其包含在列表中,除非您需要它作为简单的“标记接口”。 Yet, even then, at runtime the "is" operator (returning true or false) or "as" keyword (returning an object or null) would tell you if an object could be cast to IFoo. 然而,即便如此,在运行时,“is”运算符(返回true或false)或“as”关键字(返回对象或null)将告诉您是否可以将对象强制转换为IFoo。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM