为什么会导致CS0695?

时间:2013-03-09 22:59:57

标签: c# generics compiler-errors

public interface PipelineElement<in TIn, out TOut>
{
    IEnumerable<TOut> Run(IEnumerable<TIn> input, Action<Error> errorReporter);
}

public interface Stage
{
}

public abstract class PipelineElementBase<TIn, TOut> : PipelineElement<object, object>,
    PipelineElement<TIn, TOut> where TIn : Stage where TOut : Stage
{
    IEnumerable<object> PipelineElement<object, object>.Run(IEnumerable<object> input, Action<Error> errorReporter)
    {
        return this.Run(input.Cast<TIn>(), errorReporter).Cast<object>();
    }

    public abstract IEnumerable<TOut> Run(IEnumerable<TIn> input, Action<Error> errorReporter);
}

object未实现Stage,因此TInTOut都不能object,对吧?那么为什么编译器认为PipelineElement<object, object>PipelineElement<TIn, TOut>可以变得相同?

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

public interface MyInterface<A> { }
public class MyClass: MyInterface<string>, MyInterface<int> { }

1 个答案:

答案 0 :(得分:10)

来自Compiler Error CS0695

  

'泛型类型'不能同时实现'通用接口'和'通用接口'   接口'因为它们可能统一某些类型参数   取代。

     

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

您不能同时为抽象类实现PipelineElementBase<TIn, TOut>PipelineElement<object, object>接口。

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

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

来自C# 5.0 Language Specification

  

13.4.2已实现接口的唯一性

     

必须保留由泛型类型声明实现的接口   所有可能的构造类型都是唯一的没有这个规则,它会   无法确定正确的方法来确定   构造类型。例如,假设一个泛型类声明   被允许写成如下:

interface I<T>
{
    void F();
}
class X<U,V>: I<U>, I<V>
{
    void I<U>.F() {...}
    void I<V>.F() {...}
}
  

如果允许,则无法确定要使用哪个代码   执行以下情况:

I<int> x = new X<int,int>();
x.F();
  

确定泛型类型声明的接口列表是否为   有效,执行以下步骤:

     
      
  • 设L是通用类,结构或接口声明C中直接指定的接口列表。

  •   
  • 将L中已有的接口的任何基接口添加到L。

  •   
  • 从L。

  • 中删除所有重复项   
  • 如果从C创建的任何可能的构造类型将在类型参数替换为L之后导致L中的两个接口为   相同,那么C的声明无效。的约束   在确定所有可能的情况时,不会考虑声明   构造类型。

  •   
     

在上面的类声明X中,接口列表L由   I<U>I<V>。声明无效,因为任何构造   类型为UV类型相同会导致这两种类型   接口是相同的类型。

     

可以在不同的继承中指定接口   统一水平:

interface I<T>
{
  void F();
}
class Base<U>: I<U>
{
  void I<U>.F() {…}
}
class Derived<U,V>: Base<U>, I<V> // Ok
{
  void I<V>.F() {…}
}
     

即使Derived<U,V>同时实现I<U>,此代码仍然有效   和I<V>。代码

I<int> x = new Derived<int,int>();
x.F();
     

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

[SO编辑强调。]