3
    public interface IShape{}

    public class Rectangle : IShape{}

    public class Base{}

    public class Derived : Base{}

    public interface IFoo<out T, in U>
        where T : IShape
        where U : Base
    {
        T Convert(U myType);
    }

    public class MyFoo : IFoo<Rectangle, Derived>
    {
        public Rectangle Convert(Derived myType)
        {
            throw new NotImplementedException();
        }
    }    

    class Program
    {
        static void Main(string[] args)
        {
            IFoo<IShape, Base> hmm = new MyFoo();
        }
    }

上記のコードを考えると、コンパイラは型MyFooをに割り当てる方法を判断できません。これはIFoo<IShape, Base>おそらく、Uより少ない派生を受け入れることができることを意味する out として設定されているためです。ただし、Derivedは、まあ、 よりも派生しBaseているため、コンパイラ エラーが発生します。

この例は不自然ですが、扱っている実装はMyFooファクトリから返されるものです。

Uパラメーターとして使用されますが、ジェネリック インターフェイスに割り当てようとしたときの出力でもありますが、outここではキーワードを使用できません。どうすればこれを回避できますか?

4

2 に答える 2

1

この使用法では IFoo インターフェイスが間違っているようです。次のようにする必要があります。

public interface IFoo<out T, **out** U>

出たUまま。ジェネリックout型パラメーターは、「外側」に変化できることを意味することに注意してください。つまり、型をより広い型に暗黙的に拡張できます。Inただし、より具体的なタイプに「内側に」タイプを暗黙的に絞り込むことができることを意味します。もちろん、これらは大まかな例えにすぎません。

したがって、 の代入の場合、からへhmmのインターフェイス ジェネリック型パラメーターを暗黙的に拡大しようとしていますが、インターフェイスはそれを縮小すると宣言しています ( ):UDerivedBasein

IFoo<IShape, Base> hmm = new MyFoo();

したがって、暗黙的な変換を行うことはできません。このインターフェイスを暗黙的に拡張できるようにしたい場合は、2 番目の型引数をoutの代わりにする必要がありinます。

更新: あなたのコメントの後、大きなジレンマは in と out の両方にしたいということですが、これは実際には不可能であることがわかりましたIFoo<IShape, Base>

代入できないという事実を回避するためにコーディングする必要があるか、IFoo<IShape,Base>できることは Foo を次のように作成することです。

public class MyFoo : IFoo<Rectangle, Base>

そしてRectangle、実装内にキャストします。主なことは、同じ型パラメーターで共分散と反分散の両方を持つことはできないということです。

これは理にかなっていますか?

于 2011-05-25T15:46:55.127 に答える
0

Base を Rectangle に変換できるものは、Derived も IShape に変換します。ただし、Derived を Rectangle に変換できるものは、Base では何の役にも立たない場合があります。2 番目のパラメーターの共分散指定子を「in」にする必要があることを正しく識別しましたが、実際にサポートされているのとは反対の方法で共分散を使用しようとしています。

于 2011-05-25T19:39:09.957 に答える