C# 比较用作字典中键的对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11562996/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 18:20:06  来源:igfitidea点击:

Comparing object used as Key in Dictionary

c#dictionarycomparisonequalscontains

提问by Saint

my class:

我的课:

public class myClass
{
    public int A { get; set; }
    public int B { get; set; }
    public int C { get; set; }
    public int D { get; set; }
}

and main example:

和主要例子:

Dictionary<myClass, List<string>> dict = new Dictionary<myClass, List<string>>();
myClass first = new myClass();
first.A = 2;
first.B = 3;

myClass second = new myClass();
second.A = 2;
second.B = 3;
second.C = 5;
second.D = 6;

dict.Add(first, new List<string>());

if (dict.ContainsKey(second))
{
    //
    //should come here and update List<string> for first (and only in this example) key 
    //
}
else
{
    //
    //if myFirst object has difference vlues of A or B properties
    //
    dict.Add(second, new List<string>());
}

How to do this?

这该怎么做?

采纳答案by Scott Chamberlain

If you alwayswant the dictionary only to compare on A and B, you have two options. Either use the constructorthat implements IEqualityComparer<TKey>and put your comparison logic there, or have your class implement IEquateable<T>GetHashCode and Equalsso the default comparer will give you the results you are looking for.

如果您总是希望字典只在 A 和 B 上进行比较,您有两种选择。要么使用实现IEqualityComparer<TKey>并将比较逻辑放在那里的构造函数,要么让您的类实现GetHashCode 和 Equals,以便默认比较器将为您提供您正在寻找的结果。IEquateable<T>

If you only want to compare on A and B in your one situation you will need to use the .Keys property and the Linq extension method Containsthat allows you to pass in a IEqualityComparer<T>. However, when doing it this way you loose the speed benefits of using a Dictionary, so use it sparingly.

如果您只想在一种情况下比较 A 和 B,则需要使用 .Keys 属性和 Linq 扩展方法Contains允许您传入.Keys 属性IEqualityComparer<T>。但是,当这样做时,您会失去使用字典的速度优势,因此请谨慎使用它。

public class MyClassSpecialComparer : IEqualityComparer<myClass>
{
    public bool Equals (myClass x, myClass y)
    { 
        return x.A == y.A && x.B == y.B 
    }

    public int GetHashCode(myClass x)
    {
       return x.A.GetHashCode() + x.B.GetHashCode();
    }


}


 //Special case for when you only want it to compare this one time
 //NOTE: This will be much slower than a normal lookup.
    var myClassSpecialComparer = new MyClassSpecialComparer();
    Dictionary<myClass, List<string>> dict = new Dictionary<myClass, List<string>>();
    //(Snip)
    if (dict.Keys.Contains(second, myClassSpecialComparer ))
    {
        //
        //should come here and update List<string> for first (and only in this example) key 
        //
    }

 //If you want it to always compare
    Dictionary<myClass, List<string>> dict = new Dictionary<myClass, List<string>>(new MyClassSpecialComparer());

回答by Regfor

Override in your myClass:

在您的 myClass 中覆盖:

  • GetHashCode method

  • Equals method

  • GetHashCode 方法

  • 等于法

To implement GetHashCode method you can just XOR GetHashCodes from your integer properties.

要实现 GetHashCode 方法,您只需从整数属性中 XOR GetHashCodes 即可。

Optionally override ToString method and implement IEquatable interface

可选择覆盖 ToString 方法并实现 IEquatable 接口

回答by Peter Ritchie

By default, comparison puts objects into buckets based on their hash code. A detailed comparison is then performed (by calling Equals) if two hash codes are the same. If your class neither provides GetHashCodeor implements equality, the default object.GetHashCodewill be used--in which case nothing specific to your class will be used for value comparison semantics. Only the same reference will be found. If you don't want this, implement GetHashCodeand implement equality.

默认情况下,比较根据对象的哈希码将对象放入桶中。Equals如果两个哈希码相同,则执行详细比较(通过调用)。如果您的类既不提供GetHashCode也不实现相等,object.GetHashCode则将使用默认值——在这种情况下,不会使用任何特定于您的类的值比较语义。只会找到相同的参考。如果你不想要这个,实现GetHashCode并实现平等。

For example:

例如:

public class myClass
{
    public int A { get; set; }
    public int B { get; set; }
    public int C { get; set; }
    public int D { get; set; }

    public bool Equals(myClass other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return other.A == A && other.B == B && other.C == C && other.D == D;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof (myClass)) return false;
        return Equals((myClass) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int result = A;
            result = (result*397) ^ B;
            result = (result*397) ^ C;
            result = (result*397) ^ D;
            return result;
        }
    }
}