繁体   English   中英

在hashset字典中包含Key <myClass>

[英]ContainsKey in dictionary of hashset<myClass>

我有一本字典:

Dictionary<HashSet<myClass>, List<MyObj>> myDict = ...

我有:

HashSet<myClass> myHashSet = ...

我想检查字典(myDict)是否包含myHashSet。

我试图覆盖两种方法:

1)平等

2)GetHashCode

public class myClass
{
    public string id;
    public int number;

    public override bool Equals(object obj)
    {
        myClass other = obj as myClass;
        bool ret = false;
        if (other != null)
        {
            ret = (this.number == other.number) && (this.id == other.id);
        }
        return ret;
    }

    public override int GetHashCode()
    {
        return this.number ^ this.id.GetHashCode();
    }
};

不幸的是,在字典中找到的键,代码返回false: myDict.ContainsKey(myHashSet)

任何帮助赞赏!

仅仅因为你覆盖了myClassEquals(GetHashCode()并不意味着你覆盖了HashSet<myClass>Equals(GetHashCode() ,这就是你进行字典查找时所使用的内容。

如果您希望它工作,您需要将IEqualityComparer<HashSet<myClass>>传递给字典的构造函数,以便在执行字典查找时使用该比较器。

public class myClassSetComperer : IEqualityComparer<HashSet<myClass>>
{
    public bool Equals(HashSet<myClass> x, HashSet<myClass> y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (ReferenceEquals(null, x)) return false;
        if (ReferenceEquals(null, y)) return false;
        return x.SetEquals(y);
    }

    public int GetHashCode(HashSet<myClass> obj)
    {
        unchecked
        {
            int x = 0;
            foreach (var myClass in obj)
            {
                x = (x*397) ^ myClass?.GetHashCode() ?? 0;
            }
            return x;
        }
    }
}

//elsewhere
Dictionary<HashSet<myClass>, List<MyObj>> myDict = new Dictionary<HashSet<myClass>, List<MyObj>>(new myClassSetComperer());

非常重要注意 :如果你做任何导致Equals(GetHashCode()更改一次作为查找键的东西,字典键(和散列集)可怕地破坏。如果你修改了HashSet<myClass>或其中一个myClass对象之后你把它放在字典中,你将破坏字典和潜在的HashSet。请参阅Eric Lippert撰写的关于“GetHashCode指南和规则”的非常好的博客文章

在比较myClass的实例时,重写GetHasCode和Equal。

这是使用ContainsKey的示例,它通过对象引用进行检查。

Dictionary<HashSet<string>, List<string>> hashSetDictionary = new Dictionary<HashSet<string>, List<string>>();
            var myHashSet = new HashSet<string>();

            hashSetDictionary.Add(myHashSet, null);
            Console.WriteLine(hashSetDictionary.ContainsKey(myHashSet));

这是您的代码的更新

 public class myClass
    {
        public myClass(string text, int num)
        {
            this.Text = text;
            this.Num = num;
        }

        public string Text { get; set; }
        public int Num { get; set; }
    }

    public class MyObj { }

    public class AlwaysTrueHashSet<T> : HashSet<T>
    {
        public override bool Equals(object obj)
        {
            return this.GetHashCode() == obj.GetHashCode();
        }

        public override int GetHashCode()
        {
            return "Counting hashcode".GetHashCode();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {


            Dictionary<HashSet<myClass>, List<MyObj>> myDict = new Dictionary<HashSet<myClass>,


            List<MyObj>>();
            var myHashSet1 = new AlwaysTrueHashSet<myClass>();
            myHashSet1.Add(new myClass("123", 5));
            myDict.Add(myHashSet1, null);



            var myHashSet2 = new AlwaysTrueHashSet<myClass>();
            myHashSet2.Add(new myClass("123", 5));

            /*
             * when containsKey is invoked, it's checking if the reference of myHashSet2 is the same as myHashSet1.
             * That's the default behavior.
             * 
             * extend HashSet, and override the gethashcode and equal methods  
             */
            if (myDict.ContainsKey(myHashSet2))
            {
                Console.WriteLine("in");
                int i = 3; // it doesn't get this line }  
            }
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM