私は現実世界のベストプラクティス、他の人々が複雑なドメインを持つソリューションをどのように実装しているのかを探しています。IEqualityComparer <T>を使用するために推奨されるベストプラクティスは何ですか?
答えて
これはMSDNは(非ジェネリック)されたIEqualityComparerについて言いたいことです:
このインタフェースは、コレクションのためにカスタマイズされた等価比較を実装することができます。つまり、独自の等価定義を作成し、この定義を
IEqualityComparer
インタフェースを受け入れるコレクション型とともに使用することができます。 .NET Frameworkでは、Hashtable
、NameValueCollection
、およびOrderedDictionary
のコンストラクターがこのインターフェイスを受け入れます。このインターフェイスは、等価比較のみをサポートしています。並べ替えと並べ替えの比較のカスタマイズは、
IComparer
インターフェイスによって提供されます。
このインターフェイスの汎用バージョンは同じ機能を実行しますが、Dictionary<(Of <(TKey, TValue>)>)
コレクションに使用されているようです。
このインターフェイスを自分の目的で使用することに関するベストプラクティスです。上記の.NET Frameworkコレクションと同様の機能を持ち、独自のコレクションに同じ機能を追加したいクラスを派生または実装するときに使用することをお勧めします。これにより、.NETフレームワークがどのようにインターフェイスを使用するかが一貫しています。
つまり、カスタムコレクションを開発していて、多くのLINQやコレクション関連のメソッド(Sortなど)で使用されている等価性を消費者が制御できるようにする場合は、このインターフェイスの使用をサポートします。
私は、特定のアルゴリズムに対して異なる等価ルールをプラグインする必要があるときに最適な使い方と言います。多くのソートアルゴリズムはIComparer<T>
を受け入れる可能性があるのと同じように、発見アルゴリズムはIEqualityComparer<T>
を受け入れるかもしれないリストは、このインタフェースの多くを使用していますので、あなたはa.Substract(b)又はこれらの素敵な機能の他に言うことができます。
覚えておいて欲しいのは、オブジェクトが同じハッシュコードを返さない場合は、Equalsは呼び出されません。
私は以下のことを行いました。実際のベストプラクティスであるかどうかはわかりませんが、うまくいきました。 :)
public class GenericEqualityComparer<T> : IEqualityComparer<T>
{
private Func<T, T, Boolean> _comparer;
private Func<T, int> _hashCodeEvaluator;
public GenericEqualityComparer(Func<T, T, Boolean> comparer)
{
_comparer = comparer;
}
public GenericEqualityComparer(Func<T, T, Boolean> comparer, Func<T, int> hashCodeEvaluator)
{
_comparer = comparer;
_hashCodeEvaluator = hashCodeEvaluator;
}
#region IEqualityComparer<T> Members
public bool Equals(T x, T y)
{
return _comparer(x, y);
}
public int GetHashCode(T obj)
{
if(obj == null) {
throw new ArgumentNullException("obj");
}
if(_hashCodeEvaluator == null) {
return 0;
}
return _hashCodeEvaluator(obj);
}
#endregion
}
あなたのコレクションで使用できます。
var comparer = new GenericEqualityComparer<ShopByProduct>((x, y) => x.ProductId == y.ProductId);
var current = SelectAll().Where(p => p.ShopByGroup == group).ToList();
var toDelete = current.Except(products, comparer);
var toAdd = products.Except(current, comparer);
あなたは、カスタムメソッドGetHashCode()機能をサポートする代替計算を行うためのラムダを提供するために、代替コンストラクタを使用する必要がある場合:
var comparer = new GenericEqualityComparer<ShopByProduct>(
(x, y) => { return x.ProductId == y.ProductId; },
(x) => { return x.Product.GetHashCode()}
);
私はこのことができます願っています。 =)
IEqualityComparer<T>
の使用を検討する場合は、代わりにIEquatable<T>
を実装するクラスを作成できるかどうか考えてください。 Product
を常にIDで比較する必要がある場合は、デフォルトの比較元を使用できるようにIDを定義してください。
、請求、カスタムの比較子をお勧めします理由のいくつか残っています:クラスのインスタンスが等しいと考えることができる複数の方法がある場合は
- が。これの最も良い例は、フレームワークが
StringComparer
に6つの異なる比較文字を提供する文字列です。 - クラスが、
IEquatable<T>
として定義できないように定義されている場合。これには、コンパイラによって生成された他のクラスやクラスによって定義されたクラスが含まれます(特に匿名型、デフォルトではプロパティーとの比較が使用されます)。
比較器が必要な場合は、一般化された比較器(DMenTの回答を参照)を使用できますが、そのロジックを再利用する必要がある場合は専用クラスにカプセル化する必要があります。
class ProductByIdComparer : GenericEqualityComparer<ShopByProduct>
{
public ProductByIdComparer()
: base((x, y) => x.ProductId == y.ProductId, z => z.ProductId)
{ }
}
可能であれば、比較者を利用する必要があります。たとえば、辞書のキーとして使用されるすべての文字列(アプリ全体に渡るロジック)にToLower()
を呼び出すのではなく、大文字小文字を区別しないStringComparer
を使用するように辞書を宣言する必要があります。比較演算子を受け入れるLINQ演算子も同じです。しかし、やはり、外部から定義されるのではなく、クラスに固有でなければならない等価な動作であるかどうかを常に検討してください。
は(良い)代替案については、この記事を参照してください:Wrap a delegate in an IEqualityComparer
スクロールKeyEqualityComparerとthe importance of GetHashCodeで特に一部の部品まで。 obj.GetHashCode();
(DMenTの投稿で示唆されているように)が間違っていて、代わりに0を返さなければならない理由は、全体でdiscussionです。
- 1. SlickGridをスタイルするために推奨されるアプローチは何ですか?
- 2. ボックスを表すために推奨されるクラスは何ですか?
- 3. ベストプラクティス:CRUD操作の推奨用語は何ですか?
- 4. winformを使用してテーブルを実装するために推奨されるコントロールは何ですか?
- 5. Qt Model-View Architectureを使用するための推奨パターンは何ですか?
- 6. Webアプリケーションに非システムPerlを使用するための推奨される方法は何ですか?
- 7. 関連する一連のメソッドを非推奨にするためのベストプラクティスは何ですか?
- 8. S3に格納されたCSVファイルを解析するための推奨されるアプローチは何ですか?
- 9. iOS Share ExtensionでQuickBloxを使用するために推奨されるプロセス
- 10. SilverlightおよびiPadクライアントで使用するために推奨されるバインディング
- 11. ポイントツーポイントライブストリーミングアプリケーションに推奨されるアーキテクチャは何ですか?
- 12. スプリングブーツレストプロジェクトに推奨されるプロジェクト構造は何ですか?
- 13. ダブルに推奨される最小イプシロンは何ですか?
- 14. SQL 2000 MSDEインストールに推奨されるsetup.iniは何ですか?
- 15. uwpアプリケーションに推奨されるsqlite nugetパッケージは何ですか?
- 16. プレゼンテーションクラスでRailsビューヘルパーを使用するための推奨される方法
- 17. ES6 Reactコンポーネント内でメソッドを再利用するための推奨される方法は何ですか?
- 18. ウィンドウの下で推奨されるRubyエディタは何ですか?
- 19. Objective-Cイニシャライザを使用するために推奨される方法はどれですか?
- 20. チェーンコードデータのためのヘルパーAPIを書くために推奨される方法は何ですか?
- 21. active_model_serializers 0.10.0でキャッシュを無効にするために推奨される方法は何ですか?
- 22. オーディオストリーミングWebサーバーとして使用するために推奨される技術
- 23. 推奨されるAndroidユーティリティクラスのコレクションは何ですか?
- 24. 推奨されるBcrypt C実装は何ですか?
- 25. iPhoneアプリユーザー設定 - 推奨されるアプローチは何ですか?
- 26. 推奨されるクリーン障害メカニズムは何ですか
- 27. アンドロイドサポートライブラリの推奨されるプロゴア設定は何ですか?
- 28. 推奨されるパスカルのファイル拡張子は何ですか?
- 29. ThreadPoolExecutor/ScheduledThreadPoolExecutorに渡される推奨されるcorePoolSizeは何ですか?
- 30. Azure VMでSitecore 8.1を設定するために推奨されるアプローチは何ですか?
問題: 'obj.GetHashCode()'が意味をなさないと考えることはできません。私のポストのリンクを参照してください:http://stackoverflow.com/questions/74032/whats-the-recommended-best-practice-for-using-iequalitycomparert/4679491#4679491 –
**このデフォルトの 'obj .GetHashCode() 'フォールバック。例comparer: '(s1、s2)=> s1.ToLower()。Equals(s2.ToLower())'は、デフォルトの 'string.GetHashCode()'がfalseを返す場合に 'true'を返します。 – ulrichb