提问者:小点点

类和接口比较C#


我想对类和接口列表进行排序。 所以我的逻辑是

  • 如果类不是实现的接口,它高于接口,否则,它低于接口

我正在使用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方法中编写逻辑来按预期对我的列表进行排序呢?


共2个答案

匿名用户

我认为这不可能在iComparer上实现。 来自CompareTo

  • 对于对象A,B和C,下列条件必须为真:
  • 如果A.CompareTo(B)返回零,B.CompareTo(C)返回零,则要求A.CompareTo(C)返回零。

所以如果A从C继承,而B没有继承任何东西,那么根据您的规则,compareTo应该返回:

  • A.Compareto(B)->; 0
  • B.Compareto(C)->; 0
  • A.compareto(C)->; 1

这违反了CompareTo的要求。

另一种选择是构建层次结构的有向无环图。 那么您应该能够使用拓扑排序来对图形进行排序。

匿名用户

问题是当您比较ICATIrunnable时。 返回值为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;
    }
}