我正在尋找真實世界的最佳實踐,其他人可能如何實施複雜領域的解決方案。使用IEqualityComparer <T>的建議最佳做法是什麼?
回答
這是MSDN有什麼看法的IEqualityComparer(非通用):
該接口允許對集合定製相等比較的實施。也就是說,您可以創建您自己的相等定義,並指定將此定義與接受
IEqualityComparer
接口的集合類型一起使用。在.NET Framework中,Hashtable
,NameValueCollection
和OrderedDictionary
集合類型的構造函數接受此接口。此接口僅支持相等比較。用於分類和排序的比較定製由接口提供。
它看起來像這個接口的通用版本執行相同的功能,但用於Dictionary<(Of <(TKey, TValue>)>)
集合。
就您自己的目的使用此接口的最佳做法。我會說最好的做法是在你派生或實現一個類,這個類與上面提到的.NET框架集合有類似的功能,並且你希望爲你自己的集合添加相同的功能時使用它。這將確保您與.NET框架如何使用該界面一致。
換句話說,如果您正在開發自定義集合,並且希望允許您的用戶控制用於許多LINQ和集合相關方法(例如排序)的平等,則支持使用此接口。
我會說最好的用法是當你需要爲特定算法插入不同的相等規則時。很多相同的方式排序算法可能接受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進行比較,那麼只需將它定義爲等同就可以使用默認比較器。
儘管如此,仍有一些原因,你可能需要自定義比較:如果有可能被認爲是相等的一類的多種方式實例
- 。最好的例子是一個字符串,框架在
StringComparer
中提供了6個不同的比較器。 - 如果該類定義的方式不能將其定義爲
IEquatable<T>
。這將包括其他人定義的類和由編譯器生成的類(特別是匿名類型,默認情況下使用屬性明智的比較)。
如果您確實需要比較器,您當然可以使用通用比較器(請參閱DMenT的答案),但是如果您需要重用該邏輯,則應該將其封裝在專用類中。你甚至可以通過從通用基繼承其聲明:
class ProductByIdComparer : GenericEqualityComparer<ShopByProduct>
{
public ProductByIdComparer()
: base((x, y) => x.ProductId == y.ProductId, z => z.ProductId)
{ }
}
至於使用,您應該採取comparers的優勢在可能的情況。例如,與每個用作字典鍵的字符串(應用程序中散佈的邏輯字符)相比,不要致電ToLower()
,您應該聲明字典使用不區分大小寫的StringComparer
。接受比較器的LINQ運算符也是如此。但是,再次,總是要考慮應該是班級固有的可比較的行爲,而不是外部定義的行爲。
看到這個職位的(更好)的替代品:Wrap a delegate in an IEqualityComparer
向下滾動到KeyEqualityComparer的一部分,特別是在the importance of GetHashCode的一部分。關於爲什麼obj.GetHashCode();
(正如DMenT的帖子所建議的)是錯誤的,應該只返回0而不是discussion。
- 1. 最佳做法是什麼?
- 2. 建議在Java中將HttpSession作爲ClientSession使用嗎?最佳做法是什麼?
- 3. 什麼是ViewModel的最佳做法
- 4. log4cxx的最佳做法是什麼?
- 5. 使用jquery/javascript做下面的最佳做法是什麼?
- 6. 設置<table>大小的最佳做法是什麼?
- 7. Nginx和runit ....什麼是最佳做法
- 8. 最佳做法建議R管道%>%
- 9. WCF休息 - 最佳做法是什麼?
- 10. 構建SPA應用程序的最佳做法是什麼?
- 11. 最佳做法建議:面向對象
- 12. ASP.NET緩存,什麼是最佳做法
- 13. 使用EC2可用區域的最佳做法是什麼?
- 14. 什麼是使用codeigniter的SUM列值的最佳做法
- 15. 使用ninject的WinForms對話框的最佳做法是什麼?
- 16. 創建自動生成ID的最佳做法是什麼
- 17. 創建Spring搜索表單的最佳做法是什麼?
- 18. 構建軟件補丁的最佳做法是什麼?
- 19. 創建邀請碼的最佳做法是什麼?
- 20. 創建AJAX導航的最佳做法是什麼?
- 21. 創建數百個對象的最佳做法是什麼?
- 22. 創建統一菜單的最佳做法是什麼?
- 23. HMAC解決方案中密鑰的使用(最佳/最佳做法)是什麼?
- 24. 使用Cookies進行PHP驗證的最佳做法是什麼?
- 25. 什麼是使用TFS數據庫的最佳做法
- 26. 在nodejs中使用redis的最佳做法是什麼?
- 27. 在html中使用Anchors的最佳做法是什麼?
- 28. 使用Spark SQL查詢數據的最佳做法是什麼?
- 29. 使用CSS3/JS/jQuery的最佳做法是什麼?
- 30. 使用點斜線的最佳做法是什麼?
問題:不能認爲`obj.GetHashCode()`是有意義的。請參閱我的帖子中的鏈接:http://stackoverflow.com/questions/74032/whats-the-recommended-best-practice-for-using-iequalitycomparert/4679491#4679491 – 2011-01-13 11:28:17