[英]How to make Dictionary find object key by value
在我的應用程序中,我需要使用自定義對象作為字典的鍵。 問題是按引用比較,就像我們都知道使用值類型時,按值比較比較工作,但是在對象中按引用進行比較,因此即使對象相等,它們也會在內存堆中的不同位置存儲,因此返回false
為了做到這一點,我需要重寫Equals和GetHashCode方法(如果我錯了,我想糾正我)
我重寫了等於方法,它正在工作:
bool IsEqual = dictionaryList.Keys.First().Equals(compareKey);
返回true。
我不知道如何在我的情況下重寫GetHashCode方法(如果需要)。
我得到的例外:
The given key was not present in the dictionary.
-
給定的鍵在詞典中不存在。
我該如何解決該問題,或者我可能完全以錯誤的方式來完成它...
謝謝
using System;
using System.IO;
using System.Threading;
using System.Linq;
using System.Collections.Generic;
public sealed class Program
{
public class Options
{
public string x { get; set; }
public string y { get; set; }
}
public class Data
{
public string myData { get; set; }
}
public class KeyClass
{
public int KeyNumber { get; set; }
public List<Options> Options { get; set; }
public override bool Equals(object obj)
{
KeyClass keyClass = obj as KeyClass;
bool IsKeyNumberEqual = (KeyNumber == keyClass.KeyNumber);
bool IsOptionsEqual = true;
if (!(Options.Count == keyClass.Options.Count) || !IsKeyNumberEqual)
{
IsOptionsEqual = false;
}
else
{
for (int i = 0; i < Options.Count; i++)
{
if (!(Options[i].x == keyClass.Options[i].x) ||
!(Options[i].y == keyClass.Options[i].y))
{
IsOptionsEqual = false;
break;
}
}
}
return (IsKeyNumberEqual && IsOptionsEqual);
}
}
public static void Main()
{
try
{
List<Options> optionsList = new List<Options>();
optionsList.Add(new Options() { x = "x1", y = "y1" });
optionsList.Add(new Options() { x = "x2", y = "y2" });
Data someData = new Data() { myData = "someData" };
Data getData = new Data();
KeyClass dictionaryKey = new KeyClass() { KeyNumber = 1, Options = optionsList };
KeyClass compareKey = new KeyClass() { KeyNumber = 1, Options = optionsList };
Dictionary<KeyClass, Data> dictionaryList = new Dictionary<KeyClass, Data>();
dictionaryList.Add(dictionaryKey, someData);
bool IsEqual = dictionaryList.Keys.First().Equals(compareKey);
getData = dictionaryList[compareKey];
}
catch (Exception ex)
{
string exMessage = ex.Message;
}
}
}
為了做到這一點,我需要重寫Equals和GetHashCode方法(如果我錯了,我想糾正我)
沒錯 .NET要求比較相等的兩個對象具有相同的哈希碼。 這不限於字典。
簡單的實現是使每個對象返回相同的哈希碼。 但是,盡管允許兩個不同的對象具有相同的哈希碼,但您應將其保持在最低水平。 當您有很多哈希沖突時,字典和其他容器的性能會更差。
一個更好的實現是返回KeyNumber
(或KeyNumber.GetHashCode()
)。 如果幾乎從來沒有相同的鍵號,這是一個很好的實現,如果相同的鍵號非常有力地表明選項也將相同。
最好的實現方式是將KeyNumber
的哈希碼和您所有的Options
值組合在一起,就像Matthew Watson的答案一樣。
您需要編寫一個GetHashCode()
,其中包括有助於Equals()
方法的所有內容。
例如:
public override int GetHashCode()
{
unchecked
{
int hash = KeyNumber * 397;
foreach (var opt in Options)
{
hash = hash*23 + opt.x.GetHashCode();
hash = hash*23 + opt.y.GetHashCode();
}
return hash;
}
}
如果為Options
類實現GetHashCode(),例如:
public class Options
{
public readonly string x;
public readonly string y;
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode();
}
}
然后,您可以更簡單地編寫GetHashCode()
:
public override int GetHashCode()
{
unchecked
{
int hash = KeyNumber * 397;
foreach (var opt in Options)
hash = hash*23 + opt.GetHashCode();
return hash;
}
}
我之前忘記提及的一件重要事情:
最重要的是,將對象放入字典后,不會更改有助於相等性或哈希碼的所有字段。
如果在將對象添加到字典后更改其中任何一個,則很可能將不再能夠從字典中檢索對象。
確保這一點的最佳方法是僅將不可變字段用於相等性和哈希碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.