为什么会导致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 ,因此TInTOut都不能成为object ,对吧? 那么为什么编译器认为PipelineElementPipelineElement可以变得相同?

编辑:是的,完全可以多次实现相同的通用接口:

 public interface MyInterface { } public class MyClass: MyInterface, MyInterface { } 

来自Compiler Error CS0695

“generics类型”不能同时实现“通用接口”和“通用接口”,因为它们可能统一某些类型参数替换。

当generics类实现相同通用接口的多个参数化时会发生此错误,并且存在类型参数替换,这将使两个接口相同。 要避免此错误,请仅实现其中一个接口,或更改类型参数以避免冲突。

您不能同时为抽象类实现PipelineElementBasePipelineElement接口。

正如错误页面所说,你应该;

  • 只实施其中一个或
  • 更改类型参数以避免冲突。

来自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由II 。 声明无效,因为任何UV为相同类型的构造类型都会导致这两个接口成为相同的类型。

在不同的inheritance级别指定的接口可以统一:

 interface I { void F(); } class Base: I { void I.F() {…} } class Derived: Base, I // Ok { void I.F() {…} } 

即使Derived实现II Derived此代码也有效。 代码

 I x = new Derived(); xF(); 

调用Derived的方法,因为Derived有效地重新实现了I (§13.4.6)。

[SO编辑强调。]