- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
关于msdn page关于逆变,我发现了一个非常有趣的例子,它显示了“IComparer 中逆变的好处”
首先他们使用了一个相当奇怪的基类和派生类:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Employee : Person { }
我已经可以说这是一个糟糕的例子,因为没有任何类只是继承基类而不添加至少一点自己的东西。
然后他们创建了一个简单的 IEqualityComparer 类
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,因为它实际上只是一个 person 类!
然而在现实世界中,Employee
将至少有一个新字段,比方说 JobTitle
。鉴于很明显,当我们想要不同的 Employees 时,我们需要考虑 JobTitle 字段进行比较,并且很明显,逆变比较器(例如 person 比较器)不适合该工作,因为它无法识别任何新成员员工已定义。
当然,任何语言特性,即使是非常奇怪的特性,都可以发挥作用,即使在某些情况下它不合逻辑,但在这种情况下,我认为它不会太频繁地成为默认行为。事实上,在我看来,我们有点破坏了类型安全,当一个方法需要一个 Employee 比较器时,我们实际上可以放入一个人或什至对象比较器,它会毫无问题地编译。虽然很难想象我们的默认场景是将 Employee 视为一个对象......或基本的 Person。
那么这些接口(interface)的默认值真的是一个很好的逆变吗?
编辑:我理解什么是逆变和协变。我在问为什么那些比较接口(interface)在默认情况下被更改为逆变。
最佳答案
逆变的定义如下。一张 map F
从类型到类型映射 T
至 F<T>
在 T
中是逆变的如果每当U
和 V
是类型使得类型为 U
的每个对象可以分配给类型为 V
的变量, 每个 F<V>
类型的对象可以分配给类型为 F<U>
的变量( F
反转分配兼容性)。
特别是,如果 T -> IComparer<T>
然后注意 IComparer<Derived>
类型的变量可以接收实现 IComparer<Base>
的对象.这是逆变。
我们这么说的原因IComparer<T>
在 T
中是逆变的是因为你可以说
class SomeAnimalComparer : IComparer<Animal> { // details elided }
然后:
IComparer<Cat> catComparer = new SomeAnimalComparer();
编辑:你说:
I understand what contravariance and covariance is. I am asking why those comparing interfaces were changed to be contravariant on default.
变了?我的意思是,IComparer<T>
是“自然地”逆变的。 IComparer<T>
的定义是:
public interface IComparer<T> {
int Compare(T x, T y);
}
请注意 T
仅出现在该界面的“in”位置。也就是说,没有返回 T
实例的方法。 . 任何这样的接口(interface)在T
中是“自然地”逆变的.
鉴于此,您有什么理由不想使其逆变?如果你有一个对象知道如何比较 U
的实例, 和 V
作业是否与 U
兼容,为什么你不应该也能够将此对象视为知道如何比较 V
的实例的东西? ?这就是逆变允许的。
在逆变之前你必须换行:
class ContravarianceWrapperForIComparer<U, V> : IComparer<V> where V : U {
private readonly IComparer<U> comparer;
public ContravarianceWrapperForIComparer(IComparer<U> comparer) {
this.comparer = comparer;
}
public int Compare(V x, V y) { return this.comparer.Compare(x, y); }
}
然后你可以说
class SomeUComparer : IComparer<U> { // details elided }
IComparer<U> someUComparer = new SomeUComparer();
IComparer<V> vComparer =
new ContravarianceWrapperForIComparer<U, V>(someUComparer);
逆变允许你跳过这些咒语,只说
IComparer<V> vComparer = someUComparer;
当然以上只是当V : U
.有了逆变,你可以在任何时候做 U
赋值与 V
兼容吗? .
关于c# - IComparer 和 IEqualityComparer 接口(interface)中逆变的好处,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6434207/
我如何实现 IComparer int CompareTo(object obj) 有一个额外的参数,比如 int CompareTo(object obj, Dictionary preferenc
我在正确使用 IComparable<> 时遇到了一些麻烦界面。我还创建了一个实现 IComparer<> 的类.我几乎从一本书中复制了确切的编码示例,但对其进行了重新设计以适应我的情况,但它似乎无法
我是否应该同时实现 IComparable和通用 IComparable ?如果我只实现其中之一,是否有任何限制? 最佳答案 是的,您应该同时实现两者。 如果你实现其中一个,任何依赖于另一个的代码都会
这个问题在这里已经有了答案: When to use IComparable Vs. IComparer (8 个答案) 关闭 4 年前。 IComparable 和IComparer 接口(int
我正在尝试实现此链接的相同示例,但更注重受抚养 child 的数量。 http://www.codeproject.com/Articles/42839/Sorting-Lists-using-ICo
在大多数地方,我读到从 IComparable 继承是个好主意。和 IComparable在你的类中提供与非通用集合的兼容性。我的问题是为什么IComparable不继承自 IComparable那么
我正在使用 WPF 博士的 ObservableSortedDictionary。 构造函数如下所示: public ObservableSortedDictionary(IComparer comp
我知道 IComparable 之间有很大的区别和 IComparable一般情况下,请参阅 this , 但在这种搜索方法中,它不会有任何区别,还是会这样? public static int Se
我是 C# 的新手(6 个月的工作经验),但它看起来与 Java 非常相似,所以我感觉很自在。 但是,今天我尝试实现 IComparer 接口(interface)并想知道为什么它会给我一个错误: p
我有 Employee 类,我需要实现 IComparable 并使用 CompareTo 方法按姓名对员工进行排序。据我所知,我必须返回 1、-1 和 0,但我该如何使用这些字符串? 这是我的。 c
是否可以使用 iComparer 使用对象中的两个值对列表进行排序? 我有一个基于 value1 排序的自定义比较器类。但是对 value1 和 value2 进行排序的最佳方法是什么? 按 valu
我为装箱的 RegistryItem 对象定义了以下 IComparer: public class BoxedRegistryItemComparer : IComparer { publi
我正在尝试在相似值列表中获取唯一值,仅通过管道分隔字符串中的一个元素来区分...我不断得到至少一个对象必须实现 Icomparable。我不明白为什么我总是得到这个。我能够按该值进行分组...为什么我
假设我们有这 3 个类: Class BaseClass : System.IComparable { [int] $Value BaseClass([int] $v) {
所以我在这个错误上画了一个空白。无法比较数组中的两个元素。Array.Sort(患者);是产生错误的地方。我确实有一个 IComparable 接口(interface)和一个包含以下代码的类文件:T
我刚开始尝试使用 IEnumerable 接口(interface)。我总是只编写自定义哈希排序而不是尝试使用 native 语法,因为我对实现有些困惑。我正在尝试确定是否可以使用 BinarySea
我有一个 MyClass 类,我想像这样把它作为字典的键: Dictionary dict = new Dictionary(); 我想确保 MyClass 是唯一键,唯一性是通过查看 MyClass
在下面的代码中,我以 .NET 2.0 Framework 为目标。 我可以将 Programmer(派生)对象传递给需要 Person(基类)的 Compare 方法 但由于程序员是一个人(简单的
我正在尝试使用 IComparer 对对象数组进行排序。 我编写了代码,但它仅适用于特定对象。例如: 这门课 public class Cars { public string Name {
如何实现需要参数的 IComparer(可能不相关,但我在 Linq 查询中使用它)? 我想它应该这样称呼: ListOfObjectsToSort.orderBy(x => x, myCustomC
我是一名优秀的程序员,十分优秀!