例如,我有这些类和子类。
class Program
{
static void Main(string[] args)
{
var animals = new List<Animal> { new Wolf {kills = 5},
new Rabbit {name = "Uncle John"},
new Eagle {eyeCount = 1},
new Wolf {kills = 100},
new Rabbit { name = "Human" } };
animals.Sort();
//Suposted to be: Rabbit(Human), Rabbit(Uncle John), Wolf(5), Wolf(100), Eagle(1)
}
}
enum SortOrder { Rabbit, Wolf, Eagle }
abstract class Animal{}
class Wolf : Animal
{
public int kills = 0; //Marked public for simple initialization
}
class Rabbit : Animal
{
public string name = "Funny Little Guy"; //Marked public for simple initialization
}
class Eagle : Animal
{
public byte eyeCount = 2; //Marked public for simple initialization
}
我想对动物列表进行排序。 1) 对相同类型的其他对象进行排序(按杀死次数对狼进行排序,按名称对兔子进行排序,等等) 2) 在“排序顺序”中对子类组进行排序,因此兔子在列表中排在第一位,老鹰排在最后。
我尝试通过实现 IComparable<Animal>, IComparable<Wolf>, IComparable<Rabbit>, IComparable<Eagle>
来做到这一点接口(interface),但这让我无处可去,因为我无法完成这项工作,即使我可以,添加 1 个子类会导致大量代码工作。
这是我的尝试:
abstract class Animal : IComparable<Animal>, IComparable<Wolf>, IComparable<Rabbit>, IComparable<Eagle>
{
public abstract int CompareTo(Animal other);
public abstract int CompareTo(Wolf other);
public abstract int CompareTo(Rabbit other);
public abstract int CompareTo(Eagle other);
}
class Wolf : Animal
{
public int kills = 0; //Marked public for simple initialization
public override int CompareTo(Animal other) => other.CompareTo(this);
public override int CompareTo(Wolf other) => kills.CompareTo(kills);
public override int CompareTo(Rabbit other) => SortOrder.Wolf.CompareTo(SortOrder.Rabbit);
public override int CompareTo(Eagle other) => SortOrder.Wolf.CompareTo(SortOrder.Eagle);
}
但是通过这样做,我得到了相反的顺序,正如我所说,很难添加新的子类。
那么进行这种比较的有效方法是什么?
最佳答案
为了尽量减少添加新代码并强制新类添加到层次结构中,我会进行这种设计:
首先,我将为每种具体动物类型实现 IComparable。这很简单。其次,我会将 SortOrder OrderType 属性添加到抽象类中,并在每个具体实例中实现它。这将迫使任何扩展该类的人重新评估枚举,并可能为其添加新的值。然后,主比较函数将首先检查该属性。如果不相等,则返回类型之间的比较。如果相等,只需对两个实例调用比较,因为可以安全地假设它们具有相同的类型。
在这里实现它。我实际上不得不使用反射,因为没有其他方法来调用具体比较器。但它似乎工作得很好,只要实际类型对应于返回的枚举。
enum SortOrder { Rabbit, Wolf, Eagle }
abstract class Animal : IComparable<Animal>
{
public abstract SortOrder OrderType { get; }
public int CompareGeneric(Animal x, Animal y)
{
// use reflection to call comparer on concrete animal type
var comparerType = typeof(IComparable<>).MakeGenericType(x.GetType());
var compareMethod = comparerType.GetMethod("CompareTo");
return (int)compareMethod.Invoke(x, new object[] { y });
}
public int Compare(Animal x, Animal y)
{
// clever hack to compare the enums
var diff = x.OrderType - y.OrderType;
if (diff != 0)
return diff;
return CompareGeneric(x, y);
}
public int CompareTo(Animal other)
{
return Compare(this, other);
}
}
class Wolf : Animal, IComparable<Wolf>
{
public override SortOrder OrderType { get { return SortOrder.Wolf; } }
public int kills = 0; //Marked public for simple initialization
public int CompareTo(Wolf other)
{
return this.kills.CompareTo(other.kills);
}
}
class Rabbit : Animal, IComparable<Rabbit>
{
public override SortOrder OrderType { get { return SortOrder.Rabbit; } }
public string name = "Funny Little Guy"; //Marked public for simple initialization
public int CompareTo(Rabbit other)
{
return this.name.CompareTo(other.name);
}
}
class Eagle : Animal, IComparable<Eagle>
{
public override SortOrder OrderType { get { return SortOrder.Eagle; } }
public byte eyeCount = 2; //Marked public for simple initialization
public int CompareTo(Eagle other)
{
return this.eyeCount.CompareTo(other.eyeCount);
}
}
关于c# - 如何对子类进行比较和排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31908787/