web-dev-qa-db-ja.com

インターフェイスを使用した暗黙の演算子

暗黙の型キャストを実装しようとしているジェネリッククラスがあります。ほとんど機能しますが、インターフェースのキャストには機能しません。さらに調査したところ、該当する「インターフェイスからのユーザー定義の変換」というコンパイラエラーがあることがわかりました。これはいくつかのケースで強制される必要があることを理解していますが、私がしようとしていることは正当なケースのように見えます。

次に例を示します。

public class Foo<T> where T : IBar
{
    private readonly T instance;

    public Foo(T instance)
    {
        this.instance = instance;
    }
    public T Instance
    {
        get { return instance; }
    }
    public static implicit operator Foo<T>(T instance)
    {
        return new Foo<T>(instance);
    }
}

それを使用するコード:

var concreteReferenceToBar = new ConcreteBar();
IBar intefaceReferenceToBar = concreteReferenceToBar;
Foo<ConcreteBar> concreteFooFromConcreteBar = concreteReferenceToBar;
Foo<IBar> fooFromConcreteBar = concreteReferenceToBar;
Foo<IBar> fooFromInterfaceBar = intefaceReferenceToBar; // doesn't work

誰かが回避策を知っていますか、または私がinterfaceReferenceToBarを暗黙的にFoo<IBar>にキャストできない理由を満足できる方法で誰かが説明できますか? Fooの中で?

編集:共分散が救済を提供する可能性があるようです。 C#4.0仕様で、共分散を使用したインターフェイス型の暗黙的なキャストが可能になることを願っています。

53
Michael Meadows

これを実行できないのは、C#言語仕様で特に禁止されているためです。

クラスまたは構造体は、ソースタイプSからターゲットタイプTへの変換を宣言できますが、次のすべてが当てはまります。

  • ...
  • SもTもobjectまたはinterface-typeではありません。

そして

ユーザー定義の変換は、interface-typesとの間で変換できません。特に、この制限により、interface-typeへの変換時にユーザー定義の変換が発生せず、interface-typeは、変換されるオブジェクトが指定されたinterface-typeを実際に実装している場合にのみ成功します。

ソース

57
Adam Hughes