Я должен всегда возвращать IEnumerable <T> вместо IList <T>?

@Nicholas Riley & amp; @Kendall Helmstetter Geln & amp; @cannyboy:

Абсолютно великолепно!

Спасибо.

Учитывая ваши советы и советы других в этой теме, вот что я сделал:

Как это выглядит при использовании:

[[self appDelegate] dismissKeyboard]; (примечание: я добавил appDelegate в качестве дополнения к NSObject, чтобы я мог использовать его где угодно и где угодно)

Как это выглядит под капотом:

- (void)dismissKeyboard 
{
    UITextField *tempTextField = [[[UITextField alloc] initWithFrame:CGRectZero] autorelease];
    tempTextField.enabled = NO;
    [myRootViewController.view addSubview:tempTextField];
    [tempTextField becomeFirstResponder];
    [tempTextField resignFirstResponder];
    [tempTextField removeFromSuperview];
}

РЕДАКТИРОВАТЬ

Поправка к моему ответу включена tempTextField.enabled = NO;. Отключение текстового поля предотвратит отправку уведомлений клавиатуры UIKeyboardWillShowNotification и UIKeyboardWillHideNotification, если вы будете полагаться на эти уведомления во всем приложении.

93
задан KingNestor 2 July 2009 в 05:47
поделиться

12 ответов

Это действительно зависит от того, почему вы используете этот конкретный интерфейс.

Например, IList имеет несколько методов, которых нет в IEnumerable :

  • IndexOf (T item)
  • Insert (int index, T item)
  • RemoveAt (int index)

и Свойства:

  • T this [int index] { получить; устанавливать; }

Если вам каким-либо образом нужны эти методы, обязательно верните IList .

Кроме того, если метод, потребляющий ваш IEnumerable Результат ожидает IList , он избавит CLR от необходимости учитывать любые требуемые преобразования, таким образом оптимизируя скомпилированный код.

44
ответ дан 24 November 2019 в 06:17
поделиться

Руководства по проектированию инфраструктуры рекомендуют использовать класс Collection , когда вам нужно вернуть коллекцию, которая может быть изменена вызывающей стороной, или ReadOnlyCollection для коллекций только для чтения.

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

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

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

Лично для ORM я бы, вероятно, придерживался Collection в качестве возвращаемого значения.

65
ответ дан 24 November 2019 в 06:17
поделиться

Это зависит от ...

Возврат наименее производного типа ( IEnumerable ) предоставит вам наибольшую свободу действий для изменения базовой реализации в дальнейшем.

Возврат более производного типа ( IList ) предоставляет пользователям вашего API больше операций над результатом.

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

20
ответ дан 24 November 2019 в 06:17
поделиться

List offers the calling code many more features, such as modifying the returned object and access by index. So the question boils down to: in your application's specific use case, do you WANT to support such uses (presumably by returning a freshly constructed collection!), for the caller's convenience -- or do you want speed for the simple case when all the caller needs is to loop through the collection and you can safely return a reference to a real underlying collection without fearing this will get it erroneously changed, etc?

Only you can answer this question, and only by understanding well what your callers will want to do with the return value, and how important performance is here (how big are the collections you would be copying, how likely is this to be a bottleneck, etc).

8
ответ дан 24 November 2019 в 06:17
поделиться

One thing to consider is that if you're using a deferred-execution LINQ statement to generate your IEnumerable, calling .ToList() before you return from your method means that your items may be iterated twice - once to create the List, and once when the caller loops through, filters, or transforms your return value. When practical, I like to avoid converting the results of LINQ-to-Objects to a concrete List or Dictionary until I have to. If my caller needs a List, that's a single easy method call away - I don't need to make that decision for them, and that makes my code slightly more efficient in the cases where the caller is just doing a foreach.

11
ответ дан 24 November 2019 в 06:17
поделиться

Это не так просто, когда вы говорите о возвращаемые значения вместо входных параметров. Когда это входной параметр, вы точно знаете, что вам нужно делать. Итак, если вам нужно иметь возможность перебирать коллекцию, вы берете IEnumberable, тогда как если вам нужно добавить или удалить, вы берете IList.

В случае возвращаемого значения это сложнее. Чего ожидает ваш собеседник? Если вы вернете IEnumerable, он априори не будет знать, что может сделать из него IList. Но если вы вернете IList, он будет знать, что может перебирать его. Итак, вы должны принять во внимание, что ваш вызывающий абонент собирается делать с данными.

2
ответ дан 24 November 2019 в 06:17
поделиться

Я думаю, вы можете использовать и то, и другое, но у каждого есть применение. Обычно Список - это IEnumerable , но у вас есть функция подсчета, добавление элемента, удаление элемента

IEnumerable неэффективен для подсчета элементов

Если коллекция предназначена только для чтения или изменение коллекции контролируется Родителем , затем возвращается IList только для Count - не лучшая идея.

В Linq есть метод расширения Count () для IEnumerable , который внутри CLR будет сокращать до .Count , если базовый тип имеет IList , поэтому разница в производительности незначительна.

В общем, я считаю (мнение), что лучше по возможности возвращать IEnumerable, если вам нужно сделать добавления, добавьте эти методы в родительский класс, в противном случае потребитель затем управляет коллекцией в модели, что нарушает принципы, например, производительr.Models.Add (model) нарушает закон Деметры. Конечно, это всего лишь рекомендации, а не жесткие и быстрые правила, но до тех пор, пока вы полностью не поймете их применимость, лучше слепо следовать, чем не следовать вовсе.

public interface IManufacturer 
{
     IEnumerable<Model> Models {get;}
     void AddModel(Model model);
}

(Примечание: при использовании nNHibernate вам может потребоваться сопоставление с частным списком IList с использованием других средств доступа.)

4
ответ дан 24 November 2019 в 06:17
поделиться

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

Однако, если вам нужен подсчет элементов, не забывайте, что есть еще один уровень между IEnumerable и IList - ICollection .

0
ответ дан 24 November 2019 в 06:17
поделиться

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

0
ответ дан 24 November 2019 в 06:17
поделиться

Я могу немного ошибиться, поскольку пока никто не предлагал этого, но почему бы и нет? Вы вернули (I) Коллекция ?

Насколько я помню, Collection был предпочтительным возвращаемым типом по сравнению с List , потому что он абстрагирует реализацию. Все они реализуют IEnumerable , но мне это кажется слишком низким уровнем для работы.

0
ответ дан 24 November 2019 в 06:17
поделиться

Я думаю, вы можете использовать и то, и другое, но у каждого есть применение. В основном Список - это IEnumerable , но у вас есть функция подсчета, Добавить элемент, удалить элемент

IEnumerable неэффективен для подсчета элементов или получения определенного элемента в коллекции.

Список - это коллекция, которая идеально подходит для поиска определенных элементов, простого добавления элементов или их удаления.

Обычно я стараюсь использовать Список , где это возможно, так как это дает мне больше гибкость.

Использование Список getRecentItems () скорее, чем IList GetRecentItems()

0
ответ дан 24 November 2019 в 06:17
поделиться

В общем, вы должны требовать наиболее общие и возвращать наиболее конкретные вещи, которые вы можете. Итак, если у вас есть метод, который принимает параметр, и вам действительно нужно только то, что доступно в IEnumerable, тогда это должен быть ваш тип параметра. Если ваш метод может возвращать IList или IEnumerable, предпочтительнее возвращать IList. Это гарантирует, что он может использоваться самым широким кругом потребителей.

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

22
ответ дан 24 November 2019 в 06:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: