IComparer和IEqualityComparer接口 [英] Benefits of contravariance in IComparer & IEqualityComparer interfaces

查看:95
本文介绍了IComparer和IEqualityComparer接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

msdn页面上,我发现了一个非常有趣的示例会显示 IComparer中的逆向优势。

On the msdn page on contravariance I find a quite interesting example that shows "benefits of contravariance in IComparer"

首先,它们使用相当奇数的基数&派生类:

First they use a fairly odd base & derived classes:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Employee : Person { }

我已经可以说这是一个不好的例子,因为没有任何类可以继承基类而不添加至少一些自身的东西。

I can already say that its a bad example cause no class ever just inherits a base class without adding at least a little something of its own.

然后他们创建一个简单的IEqualityComparer类

Then they create a simple IEqualityComparer class

class PersonComparer : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {            
        ..
    }
    public int GetHashCode(Person person)
    {
       ..
    }
}

下面的示例问题。

List<Employee> employees = new List<Employee> {
               new Employee() {FirstName = "Michael", LastName = "Alexander"},
               new Employee() {FirstName = "Jeff", LastName = "Price"}
            };

IEnumerable<Employee> noduplicates = 
employees.Distinct<Employee>(new PersonComparer());

现在我的问题-首先,在这种情况下,Employee是一个不需要的类,它确实可以在这种情况下使用PersonComparer,因为实际上它只是一个人类!

Now my question - first of all in this case Employee is an unneeded class, its true that it can use PersonComparer for this situation because it is in fact just a person class!

在现实世界中,但是 Employee 至少一个新字段,例如 JobTitle 。鉴于很明显,当我们想要与员工分离时,我们需要牢记JobTitle字段进行比较,并且很清楚,Contravariant Comparer(例如人员比较器)不适合该工作,因为它无法知道任何新成员员工已定义。

In real world however Employee will have at least one new field, lets say a JobTitle. Given that its pretty clear that when we want distint Employees we would need to take that JobTitle field in mind for comparison, and its pretty clear that Contravariant Comparer such as person comparer isn't suited for that job, cause it cannot know any new members Employee has defined.

现在,即使是非常奇怪的语言功能,即使在某些情况下不合逻辑,也可以使用它,但是在这种情况下,我认为它不会经常被用作默认行为。实际上,在我看来,这是因为我们会稍微破坏类型安全性,当一种方法需要Employee比较器时,我们实际上可以放入一个人甚至对象比较器中,并且可以毫无问题地进行编译。虽然很难想象我们的默认方案是将Employee视为对象..或基本Person。

Now of course any language feature even a very odd one could have its uses, even if its illogical for some situation, but in this case I think it won't be useful far too often to be a default behavior. In fact it appears to me as we are breaking type safety a little bit, when a method expects a Employee comparer we can in fact put in a person or even object comparer and it will compile with no problems. While its hard to imagine our default scenario would be to treat Employee like an object..or basic Person.

那么这些接口的默认值是否真的是一个很好的对立性?

So is it really a good contravariance for default for those interfaces?

编辑:我了解什么是逆方差和协方差。我在问为什么那些比较接口在默认情况下会变为协变。

I understand what contravariance and covariance is. I am asking why those comparing interfaces were changed to be contravariant on default.

推荐答案

这个问题更多的是冒犯,但让我们备份一下并讨论比较器。

This question comes off more as a rant, but let's back up a moment and talk about the comparer.

IEqualityComparer< T> 在需要覆盖该对象可用的任何默认相等比较器。它可以使用自己的相等逻辑(覆盖Equals和GetHashCode),也可以使用默认的引用相等,无论如何。关键是您不希望它的默认值是什么。 IEqualityComparer< T> 允许您精确指定要用于相等的内容。它使您可以定义解决您可能遇到的许多不同问题所需的多种方法。

The IEqualityComparer<T> is useful when you need to override whatever default equality comparer is available for the object. It could be using its own equality logic (overriding Equals and GetHashCode), it could be using a default referential equality, whatever. The point is you don't want whatever its default is. IEqualityComparer<T> allows you to specify precisely what you wish to use for equality. And it lets you define as many different ways as you need to solve your many different problems you might have.

对于一个较小的派生类型,比较器可以解决许多不同的问题之一,已经存在。这就是这里所发生的一切,您可以提供比较器来解决您需要解决的问题。您可以在拥有更多派生集合的同时使用更通用的比较器。

One of those many different problems might just happen to be solvable by a comparer that already exists for a lesser derived type. That's all that's happening here, you have the ability to supply the comparer that solves the problem you need to be solved. You can use the more generic comparer while having a more derived collection.

在此问题中,您说的是只比较基本属性是可以的,但对我来说,放置一个较小的派生对象(或兄弟姐妹)

In this problem, you're saying "it's OK to compare on just the base properties but it's not OK for me to put a lesser derived object (or sibling) into the collection."

这篇关于IComparer和IEqualityComparer接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆