web-dev-qa-db-ja.com

C#4.0での一般的な共分散と反分散の実装方法

私は出席しませんでしたPDC 2008、しかし、C#4.0が一般的な共分散と反分散をサポートすると発表されたというニュースを聞きました。つまり、List<string>List<object>。それはどうですか?

Jon Skeetの本C#in Depthでは、C#ジェネリックが共分散と反分散をサポートしていない理由が説明されています。主に安全なコードを書くためです。現在、C#4.0はそれらをサポートするように変更されました。それは混乱をもたらすでしょうか?

C#4.0の詳細を知っている人はいますか?

106
Morgan Cheng

分散はsafeの方法でのみサポートされます-実際には、CLRが既に持っている能力を使用します。したがって、List<Banana>List<Fruit>(またはそれが何であれ)として使用しようとする本で私が挙げた例はまだ機能しませんが、他のいくつかのシナリオは機能します。

まず、インターフェイスとデリゲートでのみサポートされます。

第二に、インターフェース/デリゲートの作成者は、型パラメーターをin(反分散の場合)またはout(共分散の場合)として修飾する必要があります。最も明白な例はIEnumerable<T>で、これは値を「出力」することしかできません-新しい値を追加することはできません。それはIEnumerable<out T>になります。これは型の安全性を損なうものではありませんが、たとえばIEnumerable<string>を返すように宣言されたメソッドからIEnumerable<object>を返すことができます。

共分散は、インターフェイスを使用するための具体的な例を挙げるのが難しいですが、デリゲートを使用すると簡単です。 Action<T>を考慮してください-これは、Tパラメーターをとるメソッドを表すだけです。 Action<object>Action<string>としてシームレスに使用できるように変換できると便利です。objectパラメータを使用するメソッドは、string代わりに。もちろん、C#2は既にある程度の委任の共分散と反分散を持っていますが、委任タイプから別のタイプへの実際の変換(新しいインスタンスの作成)を介して-例についてはP141-144を参照してください。 C#4はこれをより一般的なものにし、(私は信じている)変換のための新しいインスタンスの作成を避けます。 (代わりに参照変換になります。)

これで少し解消されることを願っています-意味をなさない場合はお知らせください!

155
Jon Skeet

Jonがまだそれをカバーしていないわけではありませんが、Eric Lippertのブログやビデオへのリンクをいくつか紹介します。彼はそれを例で説明する素晴らしい仕事をしています。

https://blogs.msdn.Microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/

ビデオ:

https://www.youtube.com/watch?v=3MQDrKbzvq

https://www.youtube.com/watch?v=XRIadQaBYlI

https://www.youtube.com/watch?v=St9d2EDZfrg

5
kemiller2002