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

C# 比较字典中用作键的对象,c#,dictionary,comparison,equals,contains,C#,Dictionary,Comparison,Equals,Contains,我的班级: public class myClass { public int A { get; set; } public int B { get; set; } public int C { get; set; } public int D { get; set; } } 主要例子如下: Dictionary<myClass, List<string>> dict = new Dictionary<myClass, List&l

我的班级:

public class myClass
{
    public int A { get; set; }
    public int B { get; set; }
    public int C { get; set; }
    public int D { get; set; }
}
主要例子如下:

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>());
}
Dictionary dict=new Dictionary();
myClass first=新的myClass();
第一,A=2;
第一,B=3;
myClass second=新的myClass();
第二,A=2;
B=3;
第二,C=5;
第二,D=6;
dict.Add(首先,新列表());
如果(第二条)
{
//
//应该到这里来更新第一个(仅在本例中)键的列表
//
}
其他的
{
//
//如果myFirst对象具有不同的A或B属性值
//
dict.Add(第二个,新列表());
}

如何做到这一点?

如果你总是希望字典只比较A和B,你有两个选择。要么实现
IEqualityComparer
并将比较逻辑放在那里,要么让类实现GetHashCode和Equals,这样默认的比较器将为您提供所需的结果

如果您只想在一种情况下比较A和B,则需要使用.Keys属性和Linq扩展方法,该方法允许您传入一个
IEqualityComparer
。然而,当这样做的时候,你失去了使用字典的速度优势,所以要节约使用

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());
公共类MyClassSpecialComparer:IEqualityComparer
{
公共布尔等于(myClass x,myClass y)
{ 
返回x.A==y.A&&x.B==y.B
}
公共int GetHashCode(myClass x)
{
返回x.A.GetHashCode()+x.B.GetHashCode();
}
}
//特殊情况下,当你只想比较这一次
//注意:这将比普通查找慢得多。
var myClassSpecialComparer=新的myClassSpecialComparer();
Dictionary dict=新字典();
//(剪报)
if(dict.Keys.Contains(第二个,myClassSpecialComparer))
{
//
//应该到这里来更新第一个(仅在本例中)键的列表
//
}
//如果你想让它总是比较
Dictionary dict=new Dictionary(new MyClassSpecialComparer());

在myClass中重写:

  • GetHashCode方法

  • 相等法

要实现GetHashCode方法,您可以从整数属性中对GetHashCodes进行异或


可选地重写ToString方法并实现IEquatable接口。默认情况下,比较会根据对象的哈希代码将对象放入存储桶中。如果两个哈希代码相同,则执行详细比较(通过调用
Equals
)。如果您的类既不提供
GetHashCode
也不实现相等,则将使用默认的
对象.GetHashCode
——在这种情况下,不会将特定于您的类的任何内容用于值比较语义。只会找到相同的引用。如果您不希望这样,请实现
GetHashCode
并实现相等

例如:

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;
        }
    }
}

是否希望第一个值仅在A和B值相等时被视为与第二个值相等?@AlexanderEfimov这使得代码依赖于顺序,如果您将所有项异或
A=1,B=2
将生成相同的哈希值
3
has
A=2,B=1
。但是,如果将第二个项目乘以397,它将为您提供
A=1,B=2
生成`795
,但
A=2,B=1`生成
399
。这为您提供了一个更好的散列分布(注意,您应该添加not xor并用另一个素数初始化第一个数字),有关更多解释,请参阅。