我想对类和接口列表进行排序。 所以我的逻辑是
我正在使用IComparer界面对我的列表进行排序。 我的模型是这样的:
我的比较器类(如果返回1,则表示y>x,0表示x==y-1表示x>y):
public class SortedTypeComparer : IComparer<Type>
{
/// <summary>
/// Compares types
/// </summary>
public int Compare(Type x, Type y)
{
public int Compare(Type x, Type y)
{
if (y.IsAssignableFrom(x))
{
return 1;
}
else if (x.IsAssignableFrom(y))
{
return -1;
}
else if (!y.IsAssignableFrom(x) && !x.IsAssignableFrom(y) && x.IsInterface && y.IsClass)
{
return 1;
}
else if (!y.IsAssignableFrom(x) && !x.IsAssignableFrom(y) && x.IsClass && y.IsInterface)
{
return -1;
}
else
{
return 0;
}
}
}
}
我期望当我对列表排序时,它应该是:
IAnimal
IRunnable
Animal
ICat
Cat
或者:
IRunnable
IAnimal
Animal
ICat
Cat
因为IRunnable和IAnimal是“平等的”。 下面是我的用法:
var list = new List<Type>();
list.Add(typeof(IAnimal));
list.Add(typeof(IRunnable));
list.Add(typeof(ICat));
list.Add(typeof(Animal));
list.Add(typeof(Cat));
list.Sort(new SortedTypeComparer());
在这种情况下,它正在按预期工作。 但是当我改变添加到列表的顺序时,例如(把IRunnable放在最后):
var list = new List<Type>();
list.Add(typeof(IAnimal));
list.Add(typeof(ICat));
list.Add(typeof(Animal));
list.Add(typeof(Cat));
list.Add(typeof(IRunnable));
list.Sort(new SortedTypeComparer());
顺序是
IAnimal
Animal
ICat
IRunnable
Cat
这不是我所期望的,因为动物是不可驯服的。 当它比较动物和ICat时,动物似乎更高,然后当它比较ICat和IRunnable时,它说“ICat==IRunnable,所以动物应该是>;IRunnable”。 我怎样才能在Compare方法中编写逻辑来按预期对我的列表进行排序呢?
我认为这不可能在iComparer上实现。 来自CompareTo
所以如果A从C继承,而B没有继承任何东西,那么根据您的规则,compareTo应该返回:
这违反了CompareTo的要求。
另一种选择是构建层次结构的有向无环图。 那么您应该能够使用拓扑排序来对图形进行排序。
问题是当您比较ICAT
和Irunnable
时。 返回值为0,但您希望Irunnable
高于ICAT
。
如果你加上接口的数量,结果是好的:
请注意,这段代码并不涵盖所有情况,它只是为您的示例。
public int Compare(Type x, Type y)
{
if (y.IsAssignableFrom(x))
{
return 1;
}
else if (x.IsAssignableFrom(y))
{
return -1;
}
else if (x.IsInterface && y.IsClass)
{
return 1;
}
else if (x.IsClass && y.IsInterface)
{
return -1;
}
else if (x.IsInterface && y.IsInterface && y.GetInterfaces().Length == 0 && x.GetInterfaces().Length > 0)
{
return 1;
}
else if (x.IsInterface && y.IsInterface && y.GetInterfaces().Length > 0 && x.GetInterfaces().Length == 0)
{
return -1;
}
else
{
return 0;
}
}