2017-12-09 27 views
3

私はIOrderedEnumerableの宣言を見ていましたが、それはそれがTElement型のパラメータで共変ではないことを驚いていました。インタフェースIOrderedEnumerable <T>がTで共変しないのはなぜですか?

public interface IOrderedEnumerable<TElement> : IEnumerable<TElement>, IEnumerable 
{ 
    IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending); 
} 

なぜそれが共変動しなかったのか?

答えて

2

これは見落としで、.NET Coreで修正されました。ここには(閉鎖された)issueがあります。ここにはpull requestがあります。

.NET版では完全に修正されていません。これは大きな変更だと思います。 (アイデアは、別の互換性に影響する変更についてです。このanswerから取られたが、ここでも適用されます)たとえば: - Baseメソッドが呼び出されますIOrderedEnumerableが共変でない場合、

public class Base 
{ 
    public void DoSomething(IOrderedEnumerable<string> strings) 
    { 
     Console.WriteLine("Base"); 
    } 
} 

public class Derived : Base 
{ 
    public void DoSomething(IOrderedEnumerable<object> objects) 
    { 
     Console.WriteLine("Derived"); 
    } 
} 

あなたは

Derived d = new Derived(); 
d.DoSomething(new List<string>().OrderBy(c => c)); 

呼び出します。ここでそれを共変に変更するとします。次回このコードをコンパイルすると、突然Derivedメソッドが呼び出されます。

+0

+ 1のコードサンプルでは、​​メソッドのオーバーロードのために、型パラメータにIOrderedEnumerableの共変変数を設定すると問題が発生する可能性がありますが、共変にするのはかなり自然なことです。私はIEnumerableでコードサンプルをテストしました。 これは、メソッドオーバーロードと反変または一般的な分散がうまく機能しないことを意味しますか? –

+0

@ZakaryaIsserそれは自然ですが何らかの理由で行われていません。そのサンプルがそのまま動作するのは、選択するオーバーロードを解決するときに、現在のタイプの最初のメソッドが調べられるからです。一致するメソッドが見つかると、親の型は調べられません。したがって、 'IOrderedEnumerable'が共変な場合、' Derived.DoSomething'は一致し、親( 'Base')型のオーバーロードは探索されません。共変でない場合、 'Derived.DoSomething'は一致しません。そして、オーバーロードの解決は親の型に行きます。 – Evk

+0

@ ZakaryaIsserだから私はこれが共分散に関係していないことを意味する。 'IOrderedEnumerable 'の代わりに 'object'を受け入れるように' DoSomething'を変更し、もう一つは文字列を受け入れるように変更し、そこに文字列を渡すと、上の理由から 'DoSomething(オブジェクト)'オーバーロードが選択されます。 – Evk

関連する問題