代码之家  ›  专栏  ›  技术社区  ›  pseudoabdul

比较“苹果”和“橙色”对象的列表

  •  0
  • pseudoabdul  · 技术社区  · 6 年前

    这更像是一个学术练习,所以我基本上只是想弄清楚当类型不同时如何使用IComparable。

    我认为您可以让Fruit实现接口IComparable,并为每个子类型放入一堆条件语句,但这在我看来非常粗糙,可能违反了open/closed原则。我更感兴趣的是让它这样运作:

    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 回复  |  直到 6 年前
        1
  •  2
  •   nvoigt    6 年前

    我觉得有点不对劲是因为苹果和橙子没有自然的顺序。 在这种特殊情况下 你更喜欢苹果而不是桔子,但也许下一个男人想要它反过来。或者是冬天的混搭?关键是苹果和橙子没有一个独特的分类算法,把它构建成苹果或橙子甚至水果都是不对的。

    那就是 IComparer 进来了。你可以把你的比较逻辑放进去,但是你可以 比较器,并选择另一个与您所做的每种排序。所以你实现了一个 ApplesFirstComparer 冬天,然后 OrangesWithTheMostOrangeColorOnTopDoNotCareForColorOfApplesComparer 又一个又一个。基本上,你需要的每一个比较都有一个,这并不意味着苹果和橙子有一个自然的顺序。因为他们没有。

        2
  •  1
  •   xanatos    6 年前

    我会这样做:

    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

        3
  •  1
  •   Antoine V    6 年前

    这是我的主意。这看起来很简单,但会奏效的。

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

    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;}
            }  
        }