Почему аргумент рефакторинга List <Term>в IEnumerable <Term>? - PullRequest
9 голосов
/ 13 декабря 2011

У меня есть метод, который выглядит следующим образом:

    public void UpdateTermInfo(List<Term> termInfoList)
    {
        foreach (Term termInfo in termInfoList)
        {
            UpdateTermInfo(termInfo);
        }
        m_xdoc.Save(FileName.FullName);
    }

Решарпер советует мне изменить сигнатуру метода на IEnumerable<Term> вместо List<Term>. Какая польза от этого?

Ответы [ 5 ]

17 голосов
/ 13 декабря 2011

Другие ответы указывают на то, что, выбирая «больший» тип, вы разрешаете звонить вам более широкому кругу абонентов.Что само по себе является достаточной причиной, чтобы сделать это изменение.Однако есть и другие причины.Я бы порекомендовал вам внести это изменение, потому что, когда я вижу метод, который принимает список или массив, первое, что я думаю, это «что если этот метод попытается изменить элемент в моем списке / массиве?»

Вы хотите содержимое корзины, но вам требуется не только корзина, но и возможность изменять ее содержимое.Зачем вам это нужно, если вы не собираетесь использовать эту способность?Когда вы говорите: «этот метод не может принимать какую-либо старую последовательность; он должен принимать изменяемый список , который индексируется целыми числами ». Я думаю, что вы предъявляете это требование к вызывающему , потому что высобираюсь воспользоваться этой силой .

Если «я планирую испортить вашу структуру данных» - это не то, что вы намереваетесь сообщить вызывающей стороне метода, тогда не сообщайте об этом.Метод, который принимает последовательность, сообщает: «Самое большее, что я собираюсь сделать, - это прочитать эту последовательность по порядку».

6 голосов
/ 13 декабря 2011

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

Чтобы изложить при принятии запросов LINQ, можно сделать:

UpdateTermInfo(myTermList.Where(x => somefilter));

Кроме того, указание интерфейса, а не конкретного класса, позволяет другим предоставлять собственную реализацию этого интерфейса.Таким образом, вы будете «подписным», а не «пропагандистским».(Да, я только что придумал слово.)

В целом (за многими исключениями, касающимися того, какие способности вы хотите зарезервировать для возможных последующих модификаций), рекомендуется применять функции с использованиемаргументы, которые являются наиболее общими, что они могут быть.Это дает максимальную гибкость потребителю вашей функции.

В результате, если вы не можете использовать список для этой функции (возможно, потому, что в более поздний срок вы ожидаете, что вы захотите использовать такие свойства, каккак Count или оператор индекса), я настоятельно рекомендую вам использовать IList<Term> вместо List<Term> по причинам, указанным выше.

3 голосов
/ 13 декабря 2011

List реализует IEnumerable, его использование сделает вещи более гибкими. Если появился экземпляр, в котором вы не хотите использовать List и хотите использовать другой объект коллекции, он с легкостью отлит из IEnumerable.

Например, IEnumerable позволяет вам использовать Arrays и многие другие, в отличие от использования List.

.

Inumerable - это просто набор предметов, не похожий на List, где вы можете добавлять, удалять, сортировать, использовать для каждого, считать и т. Д.

0 голосов
/ 13 декабря 2011

Если вы используете List, то вы ограничиваетесь тем, что используете только конкретную реализацию List, где, как и в IEnumerable, вы можете передавать массивы, списки, коллекции, поскольку все они реализуют этот интерфейс.

0 голосов
/ 13 декабря 2011

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

Так что позже, когда вы решите, что поиск O (n) недостаточно хорош для вас, вам нужно всего лишь поменять одну строку и двигаться дальше.

...