что лучший тип набора должен возвратить в API

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

Лучшая практика изменилась здесь для возврата наборов примитивов или объектов?

например:

Order[] GetOrders();
List<Order> GetOrders();
IEnumerable<Order> GetOrders();
IQueryable<Order> Get Orders();
10
задан leora 28 June 2010 в 03:22
поделиться

4 ответа

Я думаю, что наиболее часто используемый тип - IEnumerable

  • с IEnumerable Тип возвращаемого значения вы можете использовать ключевое слово yield , что позволяет отложить перечисление и выполнение вашего метода. (Типичная жалоба, например, заключается в том, что System.IO.Path.GetFiles () НЕ возвращает IEnumerable , но возвращает массив, что означает, что при вызове метода все элементы должны быть перечислены независимо от того, нужны они вам или нет. - У вас тот же недостаток с List )
  • Большинство методов расширения LINQ работают с IEnumerable
  • Тип возвращаемого значения IEnumerable не предполагает ничего конкретного о вызывающей стороне. Если вызывающему абоненту нужен список или массив, они всегда могут его создать.
  • IEnumerable реализуется с помощью List и Array , поэтому легко изменить реализацию вашего метода и по-прежнему поддерживать предыдущий тип возвращаемого значения. .
5
ответ дан 3 December 2019 в 20:40
поделиться

Хотите, чтобы коллекция была неизменной? IEnumerable Мутабельный? IList

Вам нужны индексы? IList

Со списком или массивом потребитель API имеет полную возможность добавлять, удалять, удалять, очищать и т. Д.

С помощью IEnumerable Потребитель API получает «пакет» элементов без определенного порядка, индекса и методов для изменения коллекции.

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

В общем, я бы по умолчанию использовал IEnumerable . Я мог бы использовать List в качестве резервного поля, но только хочу, чтобы пользователь мог, например, Add () - не удалять, очищать или что-то еще , поэтому я объявляю public void Add (T item) , который просто добавляет элемент в список поддерживающих полей.

6
ответ дан 3 December 2019 в 20:40
поделиться

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

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

Если вы используете IEnumerable и выпускаете свой тип в неконтролируемую пустыню, опасайтесь этого:

class MyClass {
    private List<int> _list;
    public IEnumerable<int> Numbers {
        get { return _list; }
    }
}

Поскольку пользователь может сделать это и испортить внутреннее состояние вашего класса:

var list = (List<int>)myClass.Numbers;
list.Add(123);

Это нарушит намерение свойства "только для чтения". В таких случаях ваш геттер должен выглядеть так:

    public IEnumerable<int> Numbers {
        get { return new ReadOnlyCollection<int>(_list); }
    }

В качестве альтернативы вы можете вызвать _list.ToReadOnly(). Я написал это полностью, чтобы показать тип.

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

Если вы возвращаете коллекции только для чтения, лучше объявить член как ReadOnlyCollection, так как тогда некоторые действия выполняются быстрее (получение подсчета, доступ к элементам по индексу, копирование в другую коллекцию).

Лично я хотел бы, чтобы фреймворк включал и использовал такой интерфейс:

public interface IReadOnlyCollection<T> : IEnumerable<T>
{
    T this[int index] { get; }
    int Count { get; }
    bool Contains(T item);
    void CopyTo(T[] array, int arrayIndex);
    int IndexOf(T item);
}

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

6
ответ дан 3 December 2019 в 20:40
поделиться

В дополнение к тому, что сказали другие, я хочу добавить, что вы никогда не должны возвращать IQueryable , если вы не извлекаете объекты из какого-либо удаленного источника данных. IQueryable - это объект запроса , который будет получать результаты от имени вызывающего. При использовании LINQ IQueryable обычно принимает дерево выражений, которое будет транслироваться для использования какой-либо другой системой (например, SQL Server).

См. http://weblogs.asp.net/fredriknormen/archive/2008/12/01/returning-iqueryable-lt-t-gt.aspx для получения дополнительных сведений.

1
ответ дан 3 December 2019 в 20:40
поделиться
Другие вопросы по тегам:

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