2014-01-23 3 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 не является родовой коллекцией, и он требует необщего IComparer как Sort параметр метода.

Вы должны либо изменить коллекцию, чтобы быть родовым один, как List<string> или string[] или реализовать IComparer вместо IComparer<string>.

+0

Это похоже на работу. Благодаря! – blawford

0

return использовать Также в вашем двух верхних, если состояние после compareTo

+0

Yep, не заметил, что теперь отсортированы по алфавиту. Благодарю. – blawford

0

Проблема в том, что вы используете не общую коллекцию ArrayList. Его метод Sort() предполагает не общий набор, а не общий. А так как общий интерфейс IComparer<T> не является результатом не общего IComparer, передача этого в не будет работать.

Вместо того, что вы должны сделать, чтобы реализовать свой компаратор, следует из общего класса Comparer<T>. Этот класс реализует как общие, так и не общие интерфейсы IComparer, поэтому вам нужно будет только выполнить сравнение. Сравнение будет перенаправлено на вашу фактическую реализацию. Это позволит вам использовать компаратор, когда требуется общая или нестандартная версия.

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>

седьмых, компараторы необходимы для обработки аннулирует. Это хорошая идея, чтобы обращаться с делами о случаях, так что вы не разыгрываете их случайно.Традиционно путь - сказать, что нули меньше, чем все остальное.

Восьмой, хотя это не неправильный, чтобы вернуть какой-либо старый номер, это моя практика при написании компаратора всегда возвращать 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 Я предпочитаю реализовать более строгую версию контракта. Мне показалось странным, что трехзначная функция может юридически вернуть четыре миллиарда значений. –

Смежные вопросы