10
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れることも、実装されることTInもありません。では、なぜコンパイラはとが同一になると考えるのでしょうか?TOutobjectPipelineElement<object, object>PipelineElement<TIn, TOut>

編集: はい、同じ汎用インターフェイスを複数回実装することは完全に可能です:

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

1 に答える 1

10

からCompiler Error CS0695

'generic type' は 'generic interface' と 'generic interface' の両方を実装することはできません。なぜなら、それらはいくつかの型パラメーターの置換で統合される可能性があるからです。

このエラーは、ジェネリック クラスが同じジェネリック インターフェイスの複数のパラメーター化を実装し、2 つのインターフェイスを同一にする型パラメーター置換が存在する場合に発生します。このエラーを回避するには、インターフェイスの 1 つだけを実装するか、型パラメーターを変更して競合を回避します。

抽象クラスにPipelineElementBase<TIn, TOut>とインターフェイスの両方を実装することはできません。PipelineElement<object, object>

エラーページにあるように、次のことを行う必要があります。

  • これらの 1 つだけを実装するか、
  • 型パラメータを変更して競合を回避してください。

から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 から重複を削除します。

  • 型引数が L に代入された後、C から作成された可能性のある構築された型によって、L 内の 2 つのインターフェイスが同一になる場合、C の宣言は無効です。可能なすべての構築型を決定するときに、制約宣言は考慮されません。

上記のクラス宣言Xでは、インターフェイス リスト L は と で構成され I<U>ますI<V>。宣言は無効です。これは、構築された型が同じ型であるUV、これら 2 つのインターフェイスが同じ型になるためです。

異なる継承レベルで指定されたインターフェースを統合することができます。

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編集者による強調]

于 2013-03-09T23:10:08.267 に答える