次のインターフェイスを検討してください。
interface Test<out T> where T : struct { }
エラーや警告なしでコンパイルされます。
この質問で説明し、共分散と反分散の FAQで言及されているように:
バリアンスは、型パラメーターが参照型である場合にのみサポートされます。
では、なぜ上記のインターフェースはコンパイルされるのでしょうか? 「out」キーワードで失敗する(または少なくとも警告する)のは理にかなっています。質問は要約すると思います-out
上記の例でキーワードを使用すると違いが生じる場合はありますか?
更新: 上記のインターフェイスを見て気付かない開発者がすり抜けてしまう可能性がある、誤解を招く動作の例を次に示します。
typeof(IDummy).IsAssignableFrom(typeof(MyStruct)); // should return true
typeof(ITest<IDummy>).IsAssignableFrom(typeof(ITest<MyStruct>)); // returns false
コーダーが値の型に対してバリアンスが機能しないことを認識していない場合、キーワードtrue
のために2 行目が返されることを期待しますが、返されることはありません。out
これはまさに、この質問をするように促したバグです...
コンパイルしても予期しない結果になるコードの別の例:
ITest<MyStruct> foo = ...;
var casted = (ITest<IDummy>)foo;
私はこれが機能することを期待していますが (参照型に対する共分散の制限については知りません)、System.InvalidCastException が発生します。