Ненужное приведение к IComparer? - PullRequest
4 голосов
/ 02 ноября 2011

Я понимаю, как использовать интерфейс IComparer с вспомогательными классами, которые предоставляют собственные способы сортировки. Например, вот типичный пример, который очень похож на все примеры, которые я видел в Интернете, включая страницу интерактивной справки Microsoft:

// This helper class is used to sort an array of people by name, 
// where 'Person' is a class type.
public class PeopleNameComparer : IComparer
{
  // Test the name of each object.
  int IComparer.Compare(object o1, object o2)
  {
     Person p1 = o1 as Person;
     Person p2 = o2 as Person;
     if (p1 != null && p2 != null)
        return string.Compare(p1.Name, p2.Name);
     else
        throw new ArgumentException("Parameter is not a Person!");
  }
}

Я также понимаю, что если у нас есть массив типа Person (myPeople), мы можем отсортировать этот массив следующим образом:

Array.Sort(myPeople, new PeopleNameComparer());

В этом случае мы создаем новый объект PeopleNameComparer, который имеет тип IComparer, и передаем его в метод Array.Sort () в качестве второго параметра.

Теперь, чтобы все стало лучше, мы можем реализовать свойство, чтобы предоставить объектному пользователю более дружественный способ вызова пользовательской сортировки:

public static IComparer SortByName
{ get { return (IComparer)new PeopleNameComparer(); } }

Что я не понимаю с этим типом свойства, так это почему все примеры используют приведение (IComparer) для приведения вновь созданного вспомогательного класса (в данном примере PeopleNameComparer) в объект IComparer, когда этот объект уже имеет тип IComparer? Я пробовал без приведения, и код, кажется, работает нормально:

// This property seems to work fine without the cast?
public static IComparer SortByName
{ get { return new PeopleNameComparer(); } }

Я мог бы понять это, если бы ключевое слово 'new' возвратило простой ванильный тип System.Object, который затем должен был бы быть приведен к соответствующему IComparer, но просто не мог видеть необходимость в приведении здесь. Но я последовал примеру Microsoft, и мой пример похож на пример из моей книги по Pro C #.

Есть ли какая-то причина, по которой здесь необходим литой состав?

Ответы [ 4 ]

2 голосов
/ 02 ноября 2011

Использование явного приведения более явное . Прошу прощения за трюизм ... но это только так. Это помогает сделать код более читабельным.

В некоторых случаях явное приведение может помочь во время выполнения устранить неоднозначность приведения, если есть несколько возможных опций, но, по-видимому, этого не происходит с типом возврата. Только в выражениях. Ниже приведен типичный пример, где вам понадобится явное приведение в выражении:

public class StringEnumerable : IEnumerable, IEnumerable<String>
{
    IEnumerator<String> IEnumerable<String>.GetEnumerator()
    {
        yield return "TEST";
    }

    public IEnumerator GetEnumerator()
    {
        // without the explicit cast of `this` to the generic interface the 
        // method would call itself infinitely until a StackOverflowException occurs
        return ((IEnumerable<String>)this).GetEnumerator();
    }
}

Если вы удалите явное приведение из неуниверсальной реализации интерфейса, это вызовет бесконечный цикл.

2 голосов
/ 02 ноября 2011

Приведение избыточно.

Возможно, это могло быть необходимо до того, как код был подвергнут рефакторингу из чего-то еще.

Как правило, вы видите много ошибок в коде в течение длинных жизненных циклов системы, где изменился дизайн.

Вы также можете увидеть другие избыточные конструкции, когда языковые функции изменились (то есть автоматические свойства C #) с течением времени.

Я думаю, что избыточный код снижает читабельность, и такие инструменты, как Resharper, предупредят вас и помогут удалить их.

1 голос
/ 02 ноября 2011

Я не знаю про "все" примеры, но на самом деле 2 варианта кода должны работать одинаково.Может быть, они просто думают, что явное приведение более читабельно.

1 голос
/ 02 ноября 2011

Если ваш вопрос состоит просто в том, почему примеры приводят PeopleNameComparer к IComparer, вы правы, что в этом нет необходимости.Я полагаю, что для ясности продемонстрировать начинающим, что между результатом и интерфейсом существует подразумеваемая связь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...