编程语言
首页 > 编程语言> > c# – IComparable作为逆变的好处?

c# – IComparable作为逆变的好处?

作者:互联网

我对方差的经验很少,但在阅读之后我相信至少我理解了基本概念(即方差描述了两种类型的关系和类似投射的这两种类型的关系)之间的关系.但是,我似乎无法掌握IComparable< T>的重要性和好处了.定义为逆变.乍一看,这实际上似乎阻碍了亚型之间的可比性.我希望有人能够对此事有所了解.

解决方法:

我将解决IComparer< T>首先 – 在你的问题中没有提到它,但它稍微容易“卖”然后导致IComparable< T>.

假设你有三个类:

> Shape(具有Area属性)
>圆形:形状
>方形:形状

编写AreaComparer很容易:IComparer< Shape>.

Contravariance允许您对List< Circle>进行排序.按区域,因为IComparer< Shape> (例如AreaComparer)可转换为IComparer< Circle>.

同样,对于IComparable< T> – 如果Shape本身宣称自己是IComparable< Shape>使用Area,然后您可以再次对List< Circle>进行排序.因为每个圆圈都可以与自身形状相媲美.

现在很多时候这实际上不会成为问题,因为你有从Circle到Shape的隐式转换.但圆圈的自然能力被视为IC Comparable< Circle>在泛型方法的类型推断方面可以提供帮助.例如,假设我们有:

void Foo<T>(IComparable<T> item1, T item2)

我们试着打电话

Foo(circle1, circle2);

我不知道编译器是否会(没有逆变)能够推断出T = Shape,这会起作用……但即使它可以,它也会失败:

void Foo<T>(IComparable<T> item1, T item2) where T : ISomethingCircleImplements

我们真的希望编译器对T = Circle感到满意,我建议 – 这只有在Circle是IComparable< Circle>时才有效.通过协方差.

编辑:这是一个工作的例子:

using System;

public abstract class Shape : IComparable<Shape>
{
    public abstract double Area { get; }

    public int CompareTo(Shape other)
    {
        return Area.CompareTo(other.Area);
    }
}

public interface ISomethingCircleImplements {}

public class Circle : Shape, ISomethingCircleImplements
{
    private readonly double radius;

    public Circle(double radius)
    {
        this.radius = radius;
    }

    public override double Area { get { return radius * radius * Math.PI; } }
}

class Test
{
    static void Foo<T>(IComparable<T> item1, T item2)
        where T : ISomethingCircleImplements
    {
        Console.WriteLine(item1.CompareTo(item2));
    }

    static void Main()
    {
        Circle c1 = new Circle(10);
        Circle c2 = new Circle(20);

        Foo<Circle>(c1, c2);
    }
}

有趣的是,类型推断在这里不起作用 – 但我不确定为什么.逆变本身很好.

标签:c,contravariance,icomparable
来源: https://codeday.me/bug/20190530/1182200.html