为什么会导致CS0695?
public interface PipelineElement { IEnumerable Run(IEnumerable input, Action errorReporter); } public interface Stage { } public abstract class PipelineElementBase : PipelineElement, PipelineElement where TIn : Stage where TOut : Stage { IEnumerable PipelineElement.Run(IEnumerable input, Action errorReporter) { return this.Run(input.Cast(), errorReporter).Cast(); } public abstract IEnumerable Run(IEnumerable input, Action errorReporter); }
object
没有实现Stage
,因此TIn
和TOut
都不能成为object
,对吧? 那么为什么编译器认为PipelineElement
和PipelineElement
可以变得相同?
编辑:是的,完全可以多次实现相同的通用接口:
public interface MyInterface { } public class MyClass: MyInterface, MyInterface { }
来自Compiler Error CS0695
“generics类型”不能同时实现“通用接口”和“通用接口”,因为它们可能统一某些类型参数替换。
当generics类实现相同通用接口的多个参数化时会发生此错误,并且存在类型参数替换,这将使两个接口相同。 要避免此错误,请仅实现其中一个接口,或更改类型参数以避免冲突。
您不能同时为抽象类实现PipelineElementBase
和PipelineElement
接口。
正如错误页面所说,你应该;
- 只实施其中一个或
- 更改类型参数以避免冲突。
来自C# 5.0 Language Specification
13.4.2已实现接口的唯一性
通用类型声明实现的接口必须对所有可能的构造类型保持唯一。 如果没有这个规则,就不可能确定调用某些构造类型的正确方法。 例如,假设允许使用generics类声明,如下所示:
interface I { void F(); } class X: I, I { void I.F() {...} void I.F() {...} }
如果允许这样做,则无法确定在以下情况下要执行的代码:
I x = new X(); xF();
要确定generics类型声明的接口列表是否有效,请执行以下步骤:
设L是在generics类,结构或接口声明C中直接指定的接口列表。
添加到L中已有的接口的任何基接口。
从L中删除任何重复项。
如果从C创建的任何可能的构造类型将类型参数替换为L后,导致L中的两个接口相同,则C的声明无效。 在确定所有可能的构造类型时,不考虑约束声明。
在上面的类声明
X
,接口列表L由I
和I
。 声明无效,因为任何U
和V
为相同类型的构造类型都会导致这两个接口成为相同的类型。在不同的inheritance级别指定的接口可以统一:
interface I
{ void F(); } class Base: I { void I.F() {…} } class Derived: Base, I // Ok { void I .F() {…} } 即使
Derived
实现I
和I
Derived
此代码也有效。 代码I
x = new Derived (); xF(); 调用
Derived
的方法,因为Derived
有效地重新实现了I
(§13.4.6)。
[SO编辑强调。]