C# 使用IEqualityComparer和Equals/GethashCode覆盖之间有什么区别?

C# 使用IEqualityComparer和Equals/GethashCode覆盖之间有什么区别?,c#,equals,equality,gethashcode,iequalitycomparer,C#,Equals,Equality,Gethashcode,Iequalitycomparer,当我使用字典时,有时为了比较键,我必须更改默认的Equals含义。我发现,如果我在键的类上重写Equals和GetHashCode,或者我创建了一个实现IEqualityComparer的新类,我会得到相同的结果。那么使用IEqualityComparer和Equals/GethashCode覆盖之间有什么区别呢? 两个例子: class Customer { public string name; public int age; public Customer(stri

当我使用字典时,有时为了比较键,我必须更改默认的Equals含义。我发现,如果我在键的类上重写Equals和GetHashCode,或者我创建了一个实现IEqualityComparer的新类,我会得到相同的结果。那么使用IEqualityComparer和Equals/GethashCode覆盖之间有什么区别呢? 两个例子:

class Customer
{
    public string name;
    public int age;
    public Customer(string n, int a)
    {
        this.age = a;
        this.name = n;
    }
    public override bool Equals(object obj)
    {
        Customer c = (Customer)obj;
        return this.name == c.name && this.age == c.age;
    }
    public override int GetHashCode()
    {
        return (this.name + ";" + this.age).GetHashCode();
    }
}
  class Program
{
    static void Main(string[] args)
    {
        Customer c1 = new Customer("MArk", 21);
        Customer c2 = new Customer("MArk", 21);
        Dictionary<Customer, string> d = new Dictionary<Customer, string>();
        Console.WriteLine(c1.Equals(c2));
        try
        {
            d.Add(c1, "Joe");
            d.Add(c2, "hil");
            foreach (KeyValuePair<Customer, string> k in d)
            {
                Console.WriteLine(k.Key.name + " ; " + k.Value);
            }
        }
        catch (ArgumentException)
        {
            Console.WriteLine("Chiave già inserita in precedenza");
        }
        finally
        {
            Console.ReadLine();
        }
    }
}
class客户
{
公共字符串名称;
公共信息;
公共客户(字符串n,整数a)
{
这个年龄=a;
this.name=n;
}
公共覆盖布尔等于(对象对象对象)
{
客户c=(客户)obj;
返回this.name==c.name&&this.age==c.age;
}
公共覆盖int GetHashCode()
{
return(this.name+“;”+this.age).GetHashCode();
}
}
班级计划
{
静态void Main(字符串[]参数)
{
客户c1=新客户(“标记”,21);
客户c2=新客户(“标记”,21);
字典d=新字典();
控制台写入线(c1等于(c2));
尝试
{
d、 添加(c1,“Joe”);
d、 添加(c2,“hil”);
foreach(d中的键值对k)
{
Console.WriteLine(k.Key.name+“;”+k.Value);
}
}
捕获(异常)
{
Console.WriteLine(“先例中的交叉giáinserita”);
}
最后
{
Console.ReadLine();
}
}
}
}

第二个:

class Customer
{
    public string name;
    public int age;
    public Customer(string n, int a)
    {
        this.age = a;
        this.name = n;
    }
}
class DicEqualityComparer : EqualityComparer<Customer>
{
    public override bool Equals(Customer x, Customer y) // equals dell'equalitycomparer
    {
        return x.name == y.name && x.age == y.age;
    }
    public override int GetHashCode(Customer obj)
    {
        return (obj.name + ";" + obj.age).GetHashCode();
    }
}
class Program
{
    static void Main(string[] args)
    {
        Customer c1 = new Customer("MArk", 21);
        Customer c2 = new Customer("MArk", 21);
        DicEqualityComparer dic = new DicEqualityComparer();
        Dictionary<Customer, string> d = new Dictionary<Customer, string>(dic);
        Console.WriteLine(c1.Equals(c2));
        try
        {
            d.Add(c1, "Joe");
            d.Add(c2, "hil");
            foreach (KeyValuePair<Customer, string> k in d)
            {
                Console.WriteLine(k.Key.name + " ; " + k.Value);
            }
        }
        catch (ArgumentException)
        {
            Console.WriteLine("Chiave già inserita in precedenza");
        }
        finally
        {
            Console.ReadLine();
        }
    }
}
class客户
{
公共字符串名称;
公共信息;
公共客户(字符串n,整数a)
{
这个年龄=a;
this.name=n;
}
}
类DicEqualityComparer:EqualityComparer
{
公共覆盖布尔等于(客户x,客户y)//等于dell的equalitycomparer
{
返回x.name==y.name&&x.age==y.age;
}
公共覆盖int GetHashCode(客户obj)
{
return(obj.name+“;”+obj.age).GetHashCode();
}
}
班级计划
{
静态void Main(字符串[]参数)
{
客户c1=新客户(“标记”,21);
客户c2=新客户(“标记”,21);
DicEqualityComparer dic=新的DicEqualityComparer();
字典d=新字典(dic);
控制台写入线(c1等于(c2));
尝试
{
d、 添加(c1,“Joe”);
d、 添加(c2,“hil”);
foreach(d中的键值对k)
{
Console.WriteLine(k.Key.name+“;”+k.Value);
}
}
捕获(异常)
{
Console.WriteLine(“先例中的交叉giáinserita”);
}
最后
{
Console.ReadLine();
}
}
}
}

两个例子都有相同的结果


提前感谢。

这基本上是相同的,只是有一个细微的区别。在第一个示例中,您使用Object类型的参数重写Equals,然后必须将其强制转换为Customer,然而,在第二个示例中,您可以使用Customer类型的参数,这意味着不需要强制转换


这意味着重写Equals允许比较两个不同类型的对象(在某些情况下可能需要),但是,实现IEqualityComparer并没有提供这种自由(在某些情况下也可能需要)。

对象的
Equals()
anf
GetHashCode()
实现对象固有的平等概念。但是,您可能希望使用相等的替代概念-例如,地址对象的相等比较器仅使用邮政编码而不是完整地址。

当您覆盖
Equals
GetHashCode
时,您正在更改对象确定是否等于另一个的方式。请注意,如果使用
=
运算符比较对象,则除非您也重写该运算符,否则它将不会具有与
Equals
相同的行为

这样做会改变单个类的行为,如果其他类需要相同的逻辑,该怎么办?如果您需要“通用比较”。这就是为什么您有
IEqualityComparer

看看这个例子:

interface ICustom
{
    int Key { get; set; }
}
class Custom : ICustom
{
    public int Key { get; set; }
    public int Value { get; set; }
}
class Another : ICustom
{
    public int Key { get; set; }
}

class DicEqualityComparer : IEqualityComparer<ICustom>
{
    public bool Equals(ICustom x, ICustom y)
    {
        return x.Key == y.Key;
    }

    public int GetHashCode(ICustom obj)
    {
        return obj.Key;
    }
}
接口ICustom
{
int键{get;set;}
}
自定义类:ICustom
{
公共int密钥{get;set;}
公共int值{get;set;}
}
另一类:ICustom
{
公共int密钥{get;set;}
}
类别DicEqualityComparer:IEqualityComparer
{
公共布尔等于(ICustom x,ICustom y)
{
返回x.Key==y.Key;
}
公共int GetHashCode(ICustom obj)
{
返回对象键;
}
}
我有两个不同的类,都可以使用相同的比较器

var a = new Custom { Key = 1, Value = 2 };
var b = new Custom { Key = 1, Value = 2 };
var c = new Custom { Key = 2, Value = 2 };
var another = new Another { Key = 2 };

var d = new Dictionary<ICustom, string>(new DicEqualityComparer());

d.Add(a, "X");
// d.Add(b, "X"); // same key exception
d.Add(c, "X");
// d.Add(another, "X"); // same key exception
vara=newcustom{Key=1,Value=2};
VARB=新自定义{Key=1,Value=2};
var c=新自定义{Key=2,Value=2};
var-other=new-other{Key=2};
var d=新字典(new DicEqualityComparer());
d、 添加(a,“X”);
//d.加上(b,“X”);/同一密钥异常
d、 添加(c,“X”);
//d.加上(另一个“X”);//同一密钥异常
注意,我不必在这两个类中重写
Equals
GetHashCode
。我可以在实现
ICustom
的任何对象中使用此比较器,而无需重写比较逻辑。我还可以为“父类”创建一个
IEqualityComparer
,并在继承的类上使用。我可以让比较器以不同的方式工作,我可以让比较器比较
,而不是


因此,
IEqualityComparer
允许更大的灵活性,您可以实现通用解决方案。

在许多情况下,您可能希望使用
字典
使用100%等价以外的其他方法定位对象。作为一个简单的例子,您可能希望有一个以不区分大小写的方式匹配的字典。单程