【问题标题】:Class and Interface comparing c#类和接口比较c#
【发布时间】:2020-09-28 18:06:13
【问题描述】:

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

  • 如果类没有实现接口,则高于接口,否则,低于接口

我正在使用 IComparer 界面对列表进行排序。我的模型如下所示:

我的 Comparer 类(如果返回 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

这不是我的期望,因为 IRunnable>Animal。似乎当比较 Animal 和 ICat Animal 更高时,当它比较 ICat 和 IRunnable 时,它​​会说“ICat == IRunnable,所以 Animal 应该 > IRunnable”。如何在 Compare 方法中编写逻辑以按预期对列表进行排序?

【问题讨论】:

  • 无关:else if (!y.IsAssignableFrom(x) &amp;&amp; !x.IsAssignableFrom(y) &amp;&amp; x.IsInterface &amp;&amp; y.IsClass) - 前两个对我来说似乎是多余的。它们已经过检查。
  • 你能设置一个断点并记下比较器被调用的类型和结果是什么?或者注销...
  • 我的 Comparer 类(如果返回 1 表示 y>x,0 表示 x==y -1 表示 x>y): 这与框架的约定相反.当x 大于y 时,ComparTo(x, y) 应该返回1

标签: c# class sorting interface compare


【解决方案1】:

也许@JonasH 的答案更正确,但我是通过修复我的比较器类来做到的。我在我的方法中添加了以下条件,它在大多数情况下都是正确的:

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;
        }
    }
}

【讨论】:

    【解决方案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 的要求。

    另一种方法是构建层次结构的Directed acyclic graph。然后你应该可以使用Topological sorting 对图表进行排序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-09
      • 1970-01-01
      • 2016-02-14
      相关资源
      最近更新 更多