将list <T>中的IComparable与不同的继承相关类型的T一起使用

问题描述

这里只是一些示例类。我尝试在通用列表中使用多态,因此我希望每个列表都使用自己的Compareto-Method。我不想找到其他班级安排。我想了解为什么这行不通。

class Program
{
    static void Main(string[] args)
    {

        List<Animal> MyAnimals = new List<Animal>();
        MyAnimals.Add(new Dog() { Name = "karl",Number = 1 });
        MyAnimals.Add(new Dog() { Name = "carla",Number = 2 });
        MyAnimals.Add(new Dog() { Name = "loki",Number = 3 });
        MyAnimals.Add(new Cat() { Name = "karsten",Size = 3 });
        MyAnimals.Add(new Cat() { Name = "charlie",Size = 5 });
        MyAnimals.Add(new Cat() { Name = "mona",Size = 1 });
        MyAnimals.Add(new Cat() { Name = "sisi",Size = 2 });
        MyAnimals.sort();
        ShowList(MyAnimals);
        List<Cat> cats = new List<Cat>();
        List<Dog> dogs = new List<Dog>();

        foreach (var item in MyAnimals)
        {
            if (item is Cat)
                cats.Add(item as Cat);
            if (item is Dog)
                dogs.Add(item as Dog);
        }

        dogs.Reverse();
        dogs.sort();
        cats.sort();
        ShowList(dogs);
        ShowList(cats);

        Console.ReadKey();

    }

    private static void ShowList<T>(List<T> MyAnimals)
    {
        Console.WriteLine("List of "+MyAnimals[0].GetType().Name);
        foreach (var item in MyAnimals)
        {
            Console.WriteLine(item);
        }
    }
}

abstract class Animal  : IComparable{
    public string Name { get; set; }

    public int Compareto(object obj)
    {
        if (obj == null) return 1;

        Animal animal = obj as Animal;
        if (animal != null)
            return this.Name.Compareto(animal.Name);
        else
            throw new ArgumentException("Object is not a Animal");
    }

    public override string ToString()
    {
        return Name;
    }
}
class Dog : Animal,IComparable
{
    public int Number { get; set; }
    public override string ToString()
    {
        return base.ToString() + "\tNumber:"+ Number + "\n";
    }
    public int Compareto(object obj)
    {
        if (obj == null) return 1;

        if (obj is Dog animal)
            if (this.Number.Compareto(animal.Number) == 0)
            {
                return this.Name.Compareto(animal.Name);
            }
            else
            {
                return this.Number.Compareto(animal.Number);
            }
        else
            throw new ArgumentException("Object is not a Dog");

    }
}

class Cat : Animal,IComparable
{
    public int Size { get; set; }
    public override string ToString()
    {
        return base.ToString() + "\tNumber:" + Size + "\n";
    }

    public new int Compareto(object obj)
    {
        if (obj == null) return 1;

        if (obj is Cat animal)
            if (this.Size.Compareto(animal.Size) == 0)
            {
                return this.Name.Compareto(animal.Name);
            }
            else
            {
                return this.Size.Compareto(animal.Size);
            }
        else
            throw new ArgumentException("Object is not a Cat");

    }
}

为什么MyAnimals.sort()在Animal类中不使用Compareto()?有没有办法使用多态性?这样可以用AnimalMethod比较动物清单,而用Dogs Compareto方法比较狗清单等?

解决方法

使用IComparable对列表进行排序时。被调用的CompareTo方法将始终是在对象本身的类型上定义的方法,而不是在为列表定义的类型上定义的方法。因为CatDog覆盖了CompareTo,所以Sort方法永远不会使用CompareTo中的Animal

您可以改用过载public void Sort (Comparison<T> comparison)

private int CompareAnimals(Animal animA,Animal animB)
{
    // ... your logic to compare two Animals
}

private int CompareCats(Cat catA,Cat catB)
{
    // ... your logic to compare two Cats
}

private int CompareDogs(Dog dogA,Dog dogB)
{
    // ... your logic to compare two Dogs
}

static void Main(string[] args)
{
    List<Animal> MyAnimals = new List<Animal>();
    // Adding animals...
    MyAnimals.Sort(CompareAnimals);
    // ...
    dogs.Sort(CompareDogs);
    cats.Sort(CompareCats);
}
,

这里的问题是MyService.classDog类具有一个Cat方法,该方法 隐藏 是基类方法,并且由于CompareTo将使用项目实际类型的Sort方法,而不是为ComapareTo上的项目定义的类型,因此在尝试比较{{ 1}}和List<T>

解决此问题的一种方法是改为实现Dog接口,以便我们指定要与之进行比较的确切类型。这样,Cat方法将使用正确的实现。

还请注意,我们无需为每个派生类重新实现IComparable<T>的{​​{1}}方法(用于比较Sort属性),而只需从必要时派生类的CompareTo方法:

Animal

此外,您可能希望更改Name方法以显示类型base.CompareTo(other),而不是列表中第一个元素的派生类型(否则CompareTo显示它是一个abstract class Animal : IComparable<Animal> { public string Name { get; set; } public int CompareTo(Animal other) { if (other == null) return 1; return string.Compare(Name,other.Name); } public override string ToString() { return Name; } } class Dog : Animal,IComparable<Dog> { public int Number { get; set; } public override string ToString() { return base.ToString() + "\tNumber:" + Number + "\n"; } public int CompareTo(Dog other) { if (other == null) return 1; var numberCompare = Number.CompareTo(other.Number); return numberCompare == 0 ? base.CompareTo(other) : numberCompare; } } class Cat : Animal,IComparable<Cat> { public int Size { get; set; } public override string ToString() { return base.ToString() + "\tNumber:" + Size + "\n"; } public int CompareTo(Cat other) { if (other == null) return 1; var sizeCompare = Size.CompareTo(other.Size); return sizeCompare == 0 ? base.CompareTo(other) : sizeCompare; } } ,因为第一项是ShowList):

T

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...