8

重複の可能性:
同じ型引数に対する共変性と反変性

out次のキーワードを使用して、ジェネリック型パラメーターを共変として宣言できます。

interface ICovariant<out R>

in次のキーワードを使用して、ジェネリック型パラメーターを反変として宣言できます。

interface IContravariant<in R>

また、異なる型パラメーターに対して両方をサポートすることもできます。

interface IVariant<out R, in A>

では、単一の型パラメーターに対して両方をサポートできないのはなぜでしょうか?

4

2 に答える 2

11

では、単一の型パラメーターに対して両方をサポートできないのはなぜでしょうか?

型パラメーターが出力セーフである場合、インターフェイスはその型パラメーターでのみ共変であり、型パラメーターが入力セーフである場合、インターフェイスは型パラメーターでのみ反変であることに注意してください。

構文out Tは、それTが共変型パラメーターであることを示しています。

構文in Tは、それTが反変型パラメーターであることを示しています。

共変型パラメーターであるためT、定義上、入力に対して安全ではありません。

反変の型パラメーターであるためT、定義上、出力に対して安全ではありません。

したがって、Tは入力が安全ではなく、出力が安全ではありません。

したがって、T入力位置でTは禁止され、出力位置では禁止されます。

したがって、Tインターフェイスで指定されたメソッドの入力位置にも出力位置にも表示できません。

したがって、Tインターフェイスではまったく使用できず、型パラメーターとしては無意味です。したがって、言語設計者は、見苦しいものを避けるために、共変と反変の両方としてマークされたそのような役に立たない型をインターフェイスに含めることさえ禁止しています

interface IFoo<in and out T> { }
Foo<T> : IFoo<T> { }

その後:

IFoo<Cat> cat = (IFoo<Animal>)new Foo<Dog>();

(入力セーフと出力セーフについて調べる必要がある場合は、言語仕様の 13.1.3.1 を参照してください。)

于 2011-07-15T15:09:33.380 に答える
5

それはうまくいきません。これを考慮してください(in out存在する場合):

public class INewList<in out T>
{
    public T DoIt(T item);
}

INewList<T>より狭いタイプとより広いタイプの両方のインターフェイスと互換性があることを 期待している人がいるため、これを満たすことは不可能です。

考慮してくださいINewList<Feline>

in/out の両方が可能である場合、このインターフェイスは と同等にINewList<Animal>なりますが、型引数に拡張できるため、これは in 位置では無効になります。

... DoIt(Animal item)

new Dog()これは、元のインターフェイスから Feline が期待されていたインスタンスを渡すことができることを意味するため、機能しません。

同様に、次のことが可能になるため、アウト ポジションでは逆になります。

Puma DoIt(...)

元のインターフェイスは必ずしもピューマではなく、ネコ科の動物を返す可能性があるため、これは無効です。

于 2011-07-15T15:21:47.513 に答える