Class 和接口比较 c#
Class and Interface comparing c#
我想对 classes 和接口的列表进行排序。所以我的逻辑是
- 如果class没有实现接口则高于接口,否则低于
我正在使用 IComparer 界面对我的列表进行排序。我的模型如下所示:
My Comparer class(如果returns 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是'equal'。这是我的用法:
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
这不是我的期望,因为 IRunnable>Animal。似乎当它比较 Animal 和 ICat Animal 时更高,然后当它比较 ICat 和 IRunnable 时它说 "ICat == IRunnable, so Animal should be > IRunnable"。如何在 Compare 方法中编写逻辑以按预期对列表进行排序?
我认为 IComparer 不可能做到这一点。来自 CompareTo
- For objects A, B, and C, the following must be true:
- If A.CompareTo(B) returns zero and B.CompareTo(C) returns zero, then A.CompareTo(C) is required to return zero.
所以如果 A 继承自 C 而 B 不继承任何东西,那么根据你的规则 compareTo 应该 return:
- A.CompareTo(B) -> 0
- B.CompareTo(C) -> 0
- A.CompareTo(C) -> 1
这违反了 CompareTo 的要求。
另一种方法是构建一个 Directed acyclic graph of the hierarchy. Then you should be able to use Topological sorting 来对图表进行排序。
也许@JonasH 的回答更正确,但我通过修复我的比较器 class 做到了。我在我的方法中添加了以下条件,它适用于大多数情况:
public class SortedTypeComparer : IComparer<Type>
{
public List<Type> AllTypes { get; set; }
public SortedTypeComparer(List<Type> types)
{
AllTypes = types;
}
/// <summary>
/// Compares types
/// </summary>
public int Compare(Type x, Type y)
{
var result = CompareIsHigherOrLower(x, y);
if (result == 0)
{
var subEntitiesOfX = AllTypes.Where(a => x.IsAssignableFrom(a) && a != x);
foreach (var subTypeOfX in subEntitiesOfX)
{
result = CompareIsHigherOrLower(subTypeOfX, y);
if (result == -1)
{
return -1;//It means SubEntity of X is higher then Y and X should be > Y
}
}
var subEntitiesOfY = AllTypes.Where(a => y.IsAssignableFrom(a) && a != y);
foreach (var subType in subEntitiesOfY)
{
result = CompareIsHigherOrLower(subType, x);
if (result == -1)
{
return 1;//It means SubEntity of Y is higher then X and Y should be > X
}
}
}
return result;
}
int CompareIsHigherOrLower(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;
}
}
}
我想对 classes 和接口的列表进行排序。所以我的逻辑是
- 如果class没有实现接口则高于接口,否则低于
我正在使用 IComparer 界面对我的列表进行排序。我的模型如下所示:
My Comparer class(如果returns 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是'equal'。这是我的用法:
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
这不是我的期望,因为 IRunnable>Animal。似乎当它比较 Animal 和 ICat Animal 时更高,然后当它比较 ICat 和 IRunnable 时它说 "ICat == IRunnable, so Animal should be > IRunnable"。如何在 Compare 方法中编写逻辑以按预期对列表进行排序?
我认为 IComparer 不可能做到这一点。来自 CompareTo
- For objects A, B, and C, the following must be true:
- If A.CompareTo(B) returns zero and B.CompareTo(C) returns zero, then A.CompareTo(C) is required to return zero.
所以如果 A 继承自 C 而 B 不继承任何东西,那么根据你的规则 compareTo 应该 return:
- A.CompareTo(B) -> 0
- B.CompareTo(C) -> 0
- A.CompareTo(C) -> 1
这违反了 CompareTo 的要求。
另一种方法是构建一个 Directed acyclic graph of the hierarchy. Then you should be able to use Topological sorting 来对图表进行排序。
也许@JonasH 的回答更正确,但我通过修复我的比较器 class 做到了。我在我的方法中添加了以下条件,它适用于大多数情况:
public class SortedTypeComparer : IComparer<Type>
{
public List<Type> AllTypes { get; set; }
public SortedTypeComparer(List<Type> types)
{
AllTypes = types;
}
/// <summary>
/// Compares types
/// </summary>
public int Compare(Type x, Type y)
{
var result = CompareIsHigherOrLower(x, y);
if (result == 0)
{
var subEntitiesOfX = AllTypes.Where(a => x.IsAssignableFrom(a) && a != x);
foreach (var subTypeOfX in subEntitiesOfX)
{
result = CompareIsHigherOrLower(subTypeOfX, y);
if (result == -1)
{
return -1;//It means SubEntity of X is higher then Y and X should be > Y
}
}
var subEntitiesOfY = AllTypes.Where(a => y.IsAssignableFrom(a) && a != y);
foreach (var subType in subEntitiesOfY)
{
result = CompareIsHigherOrLower(subType, x);
if (result == -1)
{
return 1;//It means SubEntity of Y is higher then X and Y should be > X
}
}
}
return result;
}
int CompareIsHigherOrLower(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;
}
}
}