[解決済み] 2つの複雑なオブジェクトを比較する最適な方法
質問
私は、以下のような2つの複雑なオブジェクトを持っています。
Object1
と
Object2
.
5段階程度の子オブジェクトを持っています。
それらが同じかどうかを言うために最も速い方法が必要です。
C#4.0ではどうすればいいのでしょうか?
どのように解決するのですか?
実装
IEquatable<T>
(を実装する(通常は継承された
Object.Equals
と
Object.GetHashCode
メソッド) をすべてのカスタムタイプで実行します。複合型の場合は、含まれる型の
Equals
メソッドを呼び出します。含まれるコレクションの場合は
SequenceEqual
拡張メソッドを使用します。
IEquatable<T>.Equals
または
Object.Equals
を各要素に追加します。この方法は、明らかに型の定義を拡張する必要がありますが、その結果はシリアライズを含むどのような一般的な解決策よりも高速になります。
編集 : ここでは3段階のネストで工夫された例を紹介します。
値型については、通常、単にその
Equals
メソッドを呼び出すだけです。たとえフィールドやプロパティが明示的に割り当てられなかったとしても、それらはデフォルト値を持つことになります。
参照型については、まず
ReferenceEquals
これは参照の等質性をチェックするもので、偶然同じオブジェクトを参照することになった場合の効率アップに役立ちます。これは、両方の参照が NULL である場合も処理します。このチェックに失敗した場合は、インスタンスのフィールドやプロパティがNULLでないことを確認します("NULL "を避けるため)。
NullReferenceException
を避けるため)、その
Equals
メソッドを呼び出します。メンバーは適切に型付けされているので
IEquatable<T>.Equals
メソッドは直接呼び出され、オーバーライドされた
Object.Equals
メソッドが直接呼び出されます (その実行は型キャストのためにわずかに遅くなります)。
をオーバーライドすると
Object.Equals
をオーバーライドすると
Object.GetHashCode
をオーバーライドする必要があります。
public class Person : IEquatable<Person>
{
public int Age { get; set; }
public string FirstName { get; set; }
public Address Address { get; set; }
public override bool Equals(object obj)
{
return this.Equals(obj as Person);
}
public bool Equals(Person other)
{
if (other == null)
return false;
return this.Age.Equals(other.Age) &&
(
object.ReferenceEquals(this.FirstName, other.FirstName) ||
this.FirstName != null &&
this.FirstName.Equals(other.FirstName)
) &&
(
object.ReferenceEquals(this.Address, other.Address) ||
this.Address != null &&
this.Address.Equals(other.Address)
);
}
}
public class Address : IEquatable<Address>
{
public int HouseNo { get; set; }
public string Street { get; set; }
public City City { get; set; }
public override bool Equals(object obj)
{
return this.Equals(obj as Address);
}
public bool Equals(Address other)
{
if (other == null)
return false;
return this.HouseNo.Equals(other.HouseNo) &&
(
object.ReferenceEquals(this.Street, other.Street) ||
this.Street != null &&
this.Street.Equals(other.Street)
) &&
(
object.ReferenceEquals(this.City, other.City) ||
this.City != null &&
this.City.Equals(other.City)
);
}
}
public class City : IEquatable<City>
{
public string Name { get; set; }
public override bool Equals(object obj)
{
return this.Equals(obj as City);
}
public bool Equals(City other)
{
if (other == null)
return false;
return
object.ReferenceEquals(this.Name, other.Name) ||
this.Name != null &&
this.Name.Equals(other.Name);
}
}
更新
: この回答は数年前に書かれたものです。それ以来、私は
IEquality<T>
を実装することから離れました。等号には2つの概念があります。
同一性
そして
等価
. メモリ表現レベルでは、これらは一般に「参照等価」と「値等価」として区別される(詳細は
等価比較
). しかし、同じ区別がドメインレベルでも適用できる。仮に、あなたの
Person
クラスが
PersonId
プロパティがあり、現実世界の人ごとに一意である。2 つのオブジェクトが同じ
PersonId
を持つが、異なる
Age
の値は等しいとみなされるのでしょうか、それとも異なるとみなされるのでしょうか?上記の回答は、等価であることを前提にしています。しかし、多くの使用法がある
IEquality<T>
インターフェイスの多くの使用法、例えばコレクションなどでは、そのような実装が提供するのは
アイデンティティ
. 例えば、もしあなたが
HashSet<T>
を生成する場合、通常は
TryGetValue(T,T)
の呼び出しは、内容が完全に同じである等価な要素である必要はなく、単に引数のアイデンティティを共有する既存の要素を返すことを期待します。この概念は
GetHashCode
:
一般に、ミュータブルな参照型では、オーバーライドする必要があります。
GetHashCode()
の場合のみです。
- mutableではないフィールドからハッシュコードを計算できる場合、または
- mutableなオブジェクトのハッシュコードが、そのハッシュコードに依存するコレクションに含まれている間、変更されないことを保証することができます。
関連
-
[解決済み】「The breakpoint will not currently be hit」を改善するには?このドキュメントにはシンボルが読み込まれていません。" という警告はどうすれば改善されますか?
-
[解決済み] ディープクローンオブジェクト
-
[解決済み] C#のオートプロパティに初期値を与える最良の方法は何ですか?
-
[解決済み] Try-catchは私のコードをスピードアップさせるか?
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] LINQのGroup by
-
[解決済み] C#で文字を繰り返し表示する最適な方法
-
[解決済み] C#でメソッドをパラメータとして渡す
-
[解決済み] Distinct() with lambda?
-
[解決済み] 汎用クラスやメソッドのメンバからTの型を取得する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】プログラム実行中に1秒待つ
-
[解決済み】ASP.NET Core Dependency Injectionのエラーです。アクティブ化しようとしているときに、タイプのサービスを解決できません。
-
解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C# [解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C#.
-
[解決済み】トランスポート接続からデータを読み取れない:既存の接続は、リモートホストによって強制的に閉じられました。
-
[解決済み】値が期待した範囲に収まらない
-
[解決済み】5.7.57 SMTP - MAIL FROMエラー時に匿名メールを送信するためにクライアントが認証されない
-
[解決済み】IntPtrとは一体何なのか?
-
[解決済み】Unityでゲームオブジェクトのすべての子をループスルーして破壊する方法?
-
[解決済み】画像のペイントにTextureBrushを使用する方法
-
[解決済み】ファイルやアセンブリ、またはその依存関係の1つをロードできませんでした。