簡體   English   中英

C#:按列表索引的字典

[英]C#: Dictionary indexed by List

我嘗試編寫一個程序,其中Dictionary由List索引。 (相信我,我願意,是的,有選擇,但是我喜歡按列表編制索引)。 有一個最小的工作(實際上不工作,只有最后一行是一個問題)示例:

using System;
using System.Collections.Generic;

namespace test
{
    class Program
    {
    static void Main(string[] args)
    {
        Dictionary<List<String>, int> h = new Dictionary<List<string>,int>();

        List<String> w = new List<string> {"a"};
        h.Add(w, 1);

        w = new List<string>{"b"};
        h.Add(w,2);

        w = new List<string>{"a"};

        int value = 0;
        h.TryGetValue(w, out value);
        Console.WriteLine(value+" "+h[w]);
    }
}

如果有人調試該程序,他將清楚地看到h中有兩個元素,但是仍然無法通過正確的索引--- h [w]訪問這些元素。 我是錯了還是發生了什么奇怪的事情?

您的應用程序的問題源於以下事實:

new List<String> { "a" } != new List<String> { "a" }

列表是否相等將檢查兩個引用是否引用同一實例。 在這種情況下,他們沒有。 相反,您創建了兩個具有相同元素的列表...這並不使它們相等。

您可以通過創建自定義的“平等比較器”來解決此問題:

public class ListEqualityComparer<T> : IEqualityComparer<List<T>>
{
    public bool Equals(List<T> list1, List<T> list2)
    {
        return list1.SequenceEquals(list2);
    }

    public int GetHashCode(List<T> list)
    {
        if(list != null && list.Length > 0)
        {
            var hashcode = list[0].GetHashCode();
            for(var i = 1; i <= list.Length; i++)
                hashcode ^= list[i].GetHashCode();

            return hashcode;
        }

        return 0;
    }
}

然后將其傳遞給Dictionary構造函數:

Dictionary<List<String>, int> h = 
    new Dictionary<List<string>,int>(new ListEqualityComparer<String>());

問題是按列表進行索引,您要按的索引不是列表中的數據,但實際上您是通過指向該列表的內存指針(即此列表所在的內存地址)進行索引的。

您在一個內存位置創建了一個列表,然后在另一個內存位置(即,創建新實例時)創建了一個完全不同的列表。 這兩個列表即使包含相同的數據也有所不同,這意味着您可以向詞典中添加任意數量的列表。

一種解決方案是,不是按列表編制索引,而是按字符串編制索引,並使用逗號分隔的包含您列表中所有數據的List作為索引。

這將永遠無法為您服務,因為List<T>EqualsGetHashCode方法不考慮列表的內容。 如果要將對象集合用作鍵,則需要實現自己的集合類型,該類型將覆蓋Equals ,以便檢查集合中對象的相等性(也許使用Enumerable.SequenceEqual 。)

Dictionary類使用引用比較來查找指定的鍵,這就是為什么即使列表包含相同項,它們也不同的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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