19

System.Linq.ILookUpの定義は次のようになります

interface ILookup<TKey, TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable {
    int Count {
        get;
    }

    IEnumerable<TElement> this[TKey key] {
        get;
    }

    bool Contains(TKey key);
}

IEnumerableはIGrouping<TKey、TElement>で共変であり、IGrouping <TKey、TElement>はTElementで共変であり、インターフェイスはTElementのみをリターンタイプとして公開するため、ILookupもTElementで共変であると想定します。確かに、定義

interface IMyLookup<TKey, out TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable {
    int Count {
        get;
    }

    IEnumerable<TElement> this[TKey key] {
        get;
    }

    bool Contains(TKey key);
}

問題なくコンパイルできます。

では、元の定義にoutキーワードがない理由は何でしょうか。Linqの将来のバージョンが追加される可能性がありますか?

4

1 に答える 1

7

MSDNのドキュメントを追跡すると、ジェネリックスの共変性と反変性が.NET Framework 4に導入されました。それ以前は、.NETFramework2.0から.NETFramework3.5までがありましIEnumerable<T>IEnumerable<out T>次に、.NET Framework 4.0では、型パラメーターTを共分散として見ることができます。

IGrouping<TKey, TElement>ILookup<TKey, TElement>.NETFramework3.5以降に存在しています。.NET Framework 4.0では、前者はに更新されてIGrouping<out TKey, out TElement>いますが、後者は理由を指定せずに省略されています。

TKeyContains(TKey)の実装とそれをthis[TKey]防ぐため、共変することはできません。

問題に関してTElementは明確ではありません。デザイナーがそれを見逃したとは思わない。おそらく原因は将来の計画にあります。または、以下のようなことを防ぎたいと思っていましたが、理由はわかりません。

string[] strings = new[] {"a", "a", "b", "b", "b", "c"};
ILookup<string, string> lookup = strings.ToLookup(s => s); // Valid.
ILookup<string, object> lookup = strings.ToLookup(s => s); // Now invalid, but would correct if TElement was covariant (out TElement).

その問題に注意を払っている他の著者もいます:

ToLookup

注意すべき少し奇妙な点の1つは、IGroupingはTKeyとTElementで共変ですが、ILookupは両方のタイプパラメーターで不変であるということです。TKeyは不変である必要がありますが、TElementが共変であるのは合理的です。

于 2013-02-21T09:57:20.550 に答える