2014-01-23 27 views
1

我寫了下面的類,它實現的IComparer:的Array.Sort使用自定義的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

ArrayList後病症是非泛型集合,並要求非通用IComparerSort方法的參數。

您應該將集合更改爲通用集合,如List<string>string[]或實施IComparer而不是IComparer<string>

+0

這似乎有它的工作。謝謝! – blawford

0

還可以使用return你的前兩名,如果compareTo

+0

是的,沒有注意到,現在可以正確排序。謝謝。 – blawford

0

問題是您正在使用非通用集合ArrayList。它的Sort()方法需要一個非泛型比較器,而不是通用比較器。由於通用接口IComparer<T>不是從非通用IComparer派生的,所以傳入它將不起作用。

相反,你應該怎麼做來實現你的比較器來自通用的Comparer<T>類。該類實現了通用接口和非通用接口,因此您只需實現一次比較。比較將轉發給您的實際實施。這將允許您在需要通用或非通用版本時使用比較器。

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

我在做什麼錯?

你至少在做七件事情是錯誤的。

首先,您缺少兩個return陳述。其次,由於您沒有注意到缺少兩個return語句,因此您很可能缺少可以運行這些代碼路徑的測試用例。

三,幹掉你的代碼。不要重複自己。重寫此代碼,以便您撥打int.TryParse兩次,而不是八次。

第四,從不使用ArrayList後面寫的代碼,比方說2005年。使用List<string>

第五,return 0無法到達。無法訪問的代碼是一種不好的做法。重寫該方法,以便每條線都可到達。

六,ArrayList.Sort不採取IComparer<string>

第七,需要comparers處理空值。明確處理這些案件是一個好主意,這樣您就不會意外地解除引用它們。傳統上,去的方式是說空值比其他所有值都小。

第八,儘管不是錯誤要返回任何舊的數字,這是我在寫一個比較器時總是返回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; 
} 
+0

您決定不直接返回結果變量而不是檢查1/-1的任何特定原因? – SolutionYogi

+0

@solutionyogi我更喜歡實施更嚴格的合同版本。我覺得奇怪的是,三值函數可以合法返回四十億個值。 –