簡體   English   中英

如何使字典按值查找對象鍵

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM