タイトルが示すように、C# の Dictionary コレクションに .Distinct() 拡張子が含まれているのはなぜですか? この背後に正当な理由がありますか、それとも私はそれを読みすぎていますか?
5 に答える
Dictionary<TKey, TValue>
拡張子IEnumerable<KeyValuePair<TKey, TValue>>
を持つ実装。Distinct
クラス自体にはDictionary
実装がありませんDistinct
の呼び出しはDistinct
、静的拡張メソッドの呼び出しに変換されます。
Enueramble.Distinct(IEnumerable<T> source)
Dictionary
キーが異なるため(したがって、キーと値のペアが異なるため)、これは不要ですが、技術的には何も問題はありません。
は からのインターフェイスDistinct
に適用されます。辞書には一意のキーがあるため意味がありませんが、実装されているという理由だけで拡張機能が存在します。IEnumerable<KeyValuePair<TKey, TValue>>
Dictionary<TKey, TValue>
Dictionary<TKey, TValue>
IEnumerable<KeyValuePair<TKey, TValue>>
Distinct()
拡張メソッドは特に辞書ではなく、任意のIEnumerable<T>
.
Dictionary<T,U>
は であるためIEnumerable<KeyValuePair<T,U>>
、このクラスに必ずしも適切でなくても、このメソッドを取得します。
これは拡張メソッドの欠点の 1 つです。特定のクラスが適切かどうかに関係なく、最初のパラメーターに適合するすべてのクラスを「拡張」します。
Dictionary<TKey, TValue>
を実装IEnumerable<KeyValuePair<TKey, TValue>>
し、Distinct
の拡張メソッドでIEnumerable<T>
あるため、有用かどうかに関係なく無料で提供されます。
. _ Distinct
_ IEqualityComparer
_ メソッドに、使用されているものとは異なる等価の定義を使用するDictionary
カスタムを指定すると、実際に重複を見つけることができます。Distinct
IEqualityComparer
Dictionary
Distinct
前に言及されていない別の側面を追加します。他の人が述べたように、Distinct
実際には の拡張メソッドですIEnumerable<T>
。ただし、 を期待する 2 番目のものもありIEqualityComparer<T>
ます。これで、次のコードを記述できます。
class Program
{
static void Main(string[] args)
{
var map = new Dictionary<int, int> { { 1, 1 }, { 2, 1 }, { 3, 1 } };
var result = map.Distinct(new MyComparer());
}
class MyComparer : IEqualityComparer<KeyValuePair<int, int>>
{
public bool Equals(KeyValuePair<int, int> x, KeyValuePair<int, int> y)
{
return x.Value == y.Value;
}
public int GetHashCode(KeyValuePair<int, int> obj)
{
return 1;
}
}
}
マップ内のすべての値が等しいため、このプログラムはKeyValuePair
辞書内 の最初の値を返します。もちろん、これを達成するためのより良い方法があります。
これで、上記のように実際に使用できる と、そうDictionary<U, V>.Distinct(IEqualityComparer<U, V>)
でないDisitinct()
があります。マイクロソフトは、ハッシュベースのコレクション内にいるかどうかを判断するために、内部で何らかの切り替えを行うことができた可能性があります。Distinct
ただし、それはその方法に何の利点も追加しません。実際、期待される要素 (上記の例では 3 つすべて) も返します。