Array.Sort与自定义IComparer接口

时间:2014-01-23 21:25:21

标签: c# sorting arraylist icomparer

我编写了以下实现IComparer的类:

class CustomComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        int intX;
        int intY;

        if (int.TryParse(x, out intX) && int.TryParse(y, out intY)) //both numbers
        {
            intX.CompareTo(intY);
        }
        else if (!int.TryParse(x, out intX) && !int.TryParse(y, out intY)) //both letters
        {
            x.CompareTo(y);
        }
        else if (!int.TryParse(x, out intX) && int.TryParse(y, out intY)) //first is a letter, second a number
        {
            return -1;
        }
        else if (int.TryParse(x, out intX) && !int.TryParse(y, out intY)) //first is a number, second is a letter
        {
            return 1;
        }

        return 0;
    }
}

我不确定我是否做得对,但我目前无法打电话。在我的程序中,我有一个ArrayList,我试图称之为:

CustomComparer c = new CustomComparer()
myArrayList.Sort(c);

我做错了什么?

4 个答案:

答案 0 :(得分:4)

ArrayList是非泛型集合,它需要非通用IComparer作为Sort方法参数。

您应该将集合更改为通用集合,例如List<string>string[]或实现IComparer而不是IComparer<string>

答案 1 :(得分:4)

  

我做错了什么?

你至少做了七件事。

首先,您缺少两个return语句。

其次,由于您没有注意到您缺少两个return语句,因此您很可能缺少可以使用这些代码路径的测试用例。

第三,干掉你的代码。不要重复自己。重写此代码,以便您拨打int.TryParse两次,而不是八次。

第四,永远不要在之后编写的代码中使用ArrayList,比如说2005年。使用List<string>

第五,return 0无法访问。无法访问的代码是一种不好的做法。重写该方法,以便每行都可以访问。

第六,ArrayList.Sort不接受IComparer<string>

第七,比较器需要处理空值。明确处理这些案例是个好主意,这样你就不会意外地取消引用它们。传统上,要做的就是说空值小于其他所有值。

第八,尽管返回任何旧数字并不是错误,但在编写比较器时总是返回0,1或-1是我的做法。

第九,在字符串是引用等于的情况下,采用“早出”是一个好习惯。那个案子非常快,所以如果你能接受它,你应该这样做。

我倾向于像这样编写这段代码:

static int? MyParse(string s)
{
    int parsed;
    bool isValid = int.TryParse(s, out parsed);
    return isValid ? (int?)parsed : (int?) null;
}
public int Compare(string x, string y)
{
    if (ReferenceEquals(x, y)) return 0;
    if (ReferenceEquals(x, null)) return -1;
    if (ReferenceEquals(y, null)) return 1;

    // We now know that neither is null.

    int? intX = MyParse(x);
    int? intY = MyParse(y);

    if (!intX.HasValue && intY.HasValue) return -1;
    if (intX.HasValue && !intY.HasValue) return 1;

    // We now know that intX.HasValue == intY.HasValue

    int result = intX.HasValue ? intX.Value.CompareTo(intY.Value) : x.CompareTo(y);
    if (result < 0) return -1;
    if (result > 0) return 1;
    return 0;
}

答案 2 :(得分:0)

如果return

之后的条件,请在前两位使用compareTo

答案 3 :(得分:0)

问题是您使用的是非通用集合ArrayList。它的Sort()方法需要非泛型比较器,而不是通用比较器。由于通用IComparer<T>接口不是从非泛型IComparer派生的,因此将其传递将无效。

相反,您应该如何实现比较器来源于通用Comparer<T>类。此类实现了通用和非通用IComparer接口,因此您只需实现一次比较。比较将转发到您的实际实施。这将允许您在需要通用或非通用版本时使用比较器。

class CustomStringComparer : Comparer<string>
{
    public override int Compare(string x, string y)
    {
        // ...
    }
}