138


28

だから私はオブジェクトのコレクションを持っています。 正確な型は重要ではありません。 そこから、特定のプロパティのペアのすべてのユニークなペアを抽出したいと思います。

myObjectCollection.Select(item => new {Alpha = item.propOne、Bravo = item.propTwo}).Distinct();

私の質問はこうです。この場合、デフォルトのオブジェクトは等しい(それぞれのオブジェクトは新しいので、私にとっては無駄になるでしょう)を使用するのですか。 ⇒等しいインスタンス) そうでなければ、その結果を達成する方法はありますか?

8 Answer


174


Kを読んでください。 Scott Allenの素晴らしい投稿はここにあります:

短い答え(そして私は引用):

_ C#コンパイラは、匿名型のEqualsおよびGetHashCodeをオーバーライドします。 2つのオーバーライドされたメソッドの実装は、オブジェクトのハッシュコードを計算し、等価性をテストするために型のすべてのpublicプロパティを使います。 同じ匿名型の2つのオブジェクトが、それらのプロパティに対してすべて同じ値を持つ場合、それらのオブジェクトは等しくなります。 _

それで、無名型を返すクエリでDistinct()メソッドを使用することは全く安全です。


14


パブリッククラスDelegateComparer:IEqualityComparer {private Func _equals; private Func _hashCode; public DelegateComparer(Func equals、Func hashCode){_equals = equals; _hashCode = hashCode; public bool Equals(T x、T y){return _equals(x、y);} }

public int GetHashCode(T obj){if(_hashCode!= null)return _hashCode(obj); obj.GetHashCode()を返します。 }}

public static class Extensions {public static IEnumerable Distinct(このIEnumerable項目、Funcはequals、Funcはハッシュコード){return items.Distinct(new DelegateComparer(equals、hashCode)); public static IEnumerable Distinct(このIEnumerable項目、Funcは等しい){return items.Distinct(new DelegateComparer(equals、null));} }}

var uniqueItems = students.Select(s => new {FirstName = s.FirstName、LastName = s.LastName}).Distinct((a、b)=> a.FirstName == b.FirstName、c => c.FirstName .GetHashCode())。ToList();

以前のめちゃめちゃなフォーマットですみません


5


C#では機能するがVBでは機能しないことが興味深い

26文字を返します。

var MyBet = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"; MyBet.ToCharArray()
.Select(x => new {lower = x.ToString().ToLower(), upper = x.ToString().ToUpper()})
.Distinct()
.Dump();

52を返します…​

薄暗いMyBet = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ" MyBet.ToCharArray()_
.Select(Function(x) New With {.lower = x.ToString.ToLower(), .upper = x.ToString.ToUpper()}) _
.Distinct() _
.Dump()


3


私は少しテストを実行し、プロパティが値型であれば、それは問題ないように見えることを発見しました。 それらが値型ではない場合、その型はそれが機能するためにそれ自身のEqualsとGetHashCode実装を提供する必要があります。 文字列は、私が思うに、うまくいくでしょう。


2


ラムダ式を取る独自のDistinct Extensionメソッドを作成できます。 これが一例です

IEqualityComparerインターフェイスから派生するクラスを作成します。

パブリッククラスDelegateComparer:IEqualityComparer {private Func _equals; private Func _hashCode; public DelegateComparer(Func equals、Func hashCode){_equals = equals; _hashCode = hashCode; public bool Equals(T x、T y){return _equals(x、y);} }

public int GetHashCode(T obj){if(_hashCode!= null)return _hashCode(obj); obj.GetHashCode()を返します。 }}

次に、Distinct Extensionメソッドを作成してください。

public static class Extensions {public static IEnumerable Distinct(このIEnumerable項目、Funcはequals、Funcはハッシュコード){return items.Distinct(new DelegateComparer(equals、hashCode)); public static IEnumerable Distinct(このIEnumerable項目、Funcは等しい){return items.Distinct(new DelegateComparer(equals、null));} }}

そして、あなたはこの方法を使用して異なるアイテムを見つけることができます

var uniqueItems = students.Select(s => new {FirstName = s.FirstName、LastName = s.LastName}).Distinct((a、b)=> a.FirstName == b.FirstName、c => c.FirstName .GetHashCode())。ToList();


0


`+ Alpha `と ` Bravo `の両方が共通のクラスを継承する場合、 ` IEquatable +`を実装することで、親クラスでの等価性チェックを指示できます。

例えば:

public class CommonClass : IEquatable
{
    // needed for Distinct()
    public override int GetHashCode()
    {
        return base.GetHashCode();
    }

    public bool Equals(CommonClass other)
    {
        if (other == null) return false;
        return [equality test];
    }
}


0


ちょっとそこに私は同じ問題を抱えていた、そして私は解決策を見つけた。 IEquatableインターフェイスを実装するか、単に(Equalsをオーバーライドする必要があります。 しかし、これはトリックではなく、GetHashCodeメソッドのトリックです。 クラスのオブジェクトのハッシュコードを返すべきではありませんが、そのように比較したいプロパティのハッシュを返すべきです。

public override bool次の値と等しい(オブジェクトobj){Person p = obj as Person; if(obj == null)がfalseを返す場合if(object.ReferenceEquals(p、this))はtrueを返します。 if(p.Age == this.Age

ご覧のとおり、personというクラスに3つのプロパティ(Name、Age、IsEgyptian、「自分はだから」)があります。GetHashCodeでは、PersonオブジェクトではなくNameプロパティのハッシュを返しました。

それを試してみて、それはISAを動作します。 ありがとうございます、Modather Sadik


0


VB.NETで機能させるには、次のように、匿名型のすべてのプロパティの前に `+ Key`キーワードを指定する必要があります。

myObjectCollection.Select(Function(item) New With
{
    Key .Alpha = item.propOne,
    Key .Bravo = item.propTwo
}).Distinct()

私はこれに苦労していました、私はVB.NETがこのタイプの機能をサポートしなかったと思いました、しかし実際にそれはサポートします。