比较“ Apple”和“ Orange”对象的列表

时间:2018-07-26 08:50:42

标签: c# generics icomparable

这比其他任何事情都更具学术性,因此我基本上只是想弄清楚类型不同时如何使用IComparable。

因此,我们有一个水果类,以及派生类“ Apple”和“ Orange”。假设我要列出一个水果清单,使所有苹果都位于橙子之前。最好的方法是什么?

我认为您可以使Fruit实现IComparable接口,并为非常子类型放入一堆条件语句,但是对我来说,这似乎很粗糙,并且可能违反了开放/封闭原则。我对使它以这种方式工作更感兴趣:

public abstract class Fruit : IComparable<Fruit>
{
    public abstract int CompareTo(Fruit other);
}

public class Apple : Fruit, IComparable<Orange>
{
    public override int CompareTo(Fruit other)
    {
        if(other is Orange)
        {
            this.CompareTo((Orange)other);
        }
        return 0;
    }

    public virtual int CompareTo(Orange other)
    {
        return -1;
    }
}

public class Orange : Fruit, IComparable<Apple>
{
    public override int CompareTo(Fruit other)
    {
        if (other is Apple)
        {
            this.CompareTo((Apple)other);
        }
        return 0;
    }

    public virtual int CompareTo(Apple other)
    {
        return 1;
    }
}

我在这里的主要目标是让IComparable处理交叉类型。我尝试加载各种水果的清单,但可惜没有排序。也许我对CompareTo的返回值的理解有些奇怪。这种方法是否有希望,是否存在比明显方法有用的任何场景?

3 个答案:

答案 0 :(得分:1)

它将立即变得可怕...每个水果都必须彼此了解...如果您有10个水果,则有90条代码来决定如何比较它们。

我会做类似的事情:

public abstract class Fruit : IComparable<Fruit>
{
    // It should be unique for each fruit type
    public abstract int Importance { get; }

    public int CompareTo(Fruit other)
    {
        // If you want, you can do some tests here, that 
        // are common to all the Fruit. I wouldn't,
        // because this would create an ordering with
        // higher priority than Importance.

        int cmp = Importance.CompareTo(other.Importance);

        if (cmp != 0)
        {
            return cmp;
        }

        if (GetType() != other.GetType())
        {
            throw new ApplicationException("Different type of fruit must have different Importance");
        }

        // Other Fruit comparisons

        // We know the Fruit have the same type (see above)
        return CompareToInternal(other);
    }

    // Comparison of subtype of Fruit
    public abstract int CompareToInternal(Fruit other);
}

因此,只有相同类型的Fruit是可比较的。其他水果的Importance是预先确定的(苹果比猕猴桃好),还有一个抽象的CompareToInternal用于进行子类型比较(在同一类型的水果中……苹果与苹果,奇异果与猕猴桃)

答案 1 :(得分:1)

我觉得这有点奇怪,因为苹果和橘子没有天然的顺序。 在这种特定情况下,您更喜欢苹果而不是橘子,但也许下一个家伙反过来想要它。还是在冬天混合?关键是苹果和橘子没有一个独特的排序算法,将其构建到苹果,橘子甚至水果中都是错误的。

这就是IComparer的用处。您可以在其中放置比较逻辑,但是可以有许多个比较器,并根据每种排序选择另一个。因此,您在冬季实施了ApplesFirstComparer,然后实施了OrangesWithTheMostOrangeColorOnTopDoNotCareForColorOfApplesComparer和另一个。基本上,您需要进行的每个比较都需要一个,而不意味着苹果和橘子具有自然的顺序。因为他们没有。

答案 2 :(得分:1)

这是我的主意。看起来很简单,但是可以正常工作。

您可以标记每个类的唯一顺序并将其排序。

public abstract class Fruit
{
    public int MyOrder {get;}
}

public class Apple : Fruit
{    
}

public class Orange : Fruit
{    
}

现在,您想要所有的苹果都比橘子先。设置值并对其进行排序。

//Suppose that this is your list fruits
var fruits = new List<Fruit>();
fruits.OfType<Apple>().ForEach(a=> a.MyOrder = 1);
fruits.OfType<Orange>().ForEach(a=> a.MyOrder = 2);
var sorted = fruits.OrderBy(x=>MyOrder);

如果您有多个水果,那将是一个不利条件。

但是如果您的订单没有变化,就像苹果总是比橙子先。在课堂上设置MyOrder

    public abstract class Fruit
    {
        public abstract int MyOrder {get;}
    }

    public class Apple : Fruit
    {    
        public override int MyOrder {
            get { return 1;}
        }
    }

    public class Orange : Fruit
    {  
        public override int MyOrder {
            get { return 2;}
        }  
    }