问题描述
这里只是一些示例类。我尝试在通用列表中使用多态,因此我希望每个列表都使用自己的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
方法将始终是在对象本身的类型上定义的方法,而不是在为列表定义的类型上定义的方法。因为Cat
和Dog
覆盖了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.class
和Dog
类具有一个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