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

Вы используете ToList()?

У вас есть тип по умолчанию, который вы предпочитаете использовать в своих отношениях с результатами запросов LINQ?

По умолчанию LINQ вернет IEnumerable<> или, возможно, IOrderedEnumerable<>. Мы обнаружили, что a List<>, как правило, более полезен для нас, поэтому мы привыкли к ToList() выполнению наших запросов большую часть времени и, конечно, используя List<> в наших аргументах функции и возвращаемых значениях.

Единственное исключение из этого - в LINQ to SQL, где вызов .ToList() должен преждевременно перечислять IEnumerable.

Мы также широко используем WCF, тип коллекции по умолчанию которого равен System.Array. Мы всегда меняем это на System.Collections.Generic.List в диалоговом окне "Параметры ссылки на службу" в VS2008 для согласованности с остальной частью нашей кодовой базы.

Чем вы занимаетесь?

4b9b3361

Ответ 1

ToList всегда оценивает последовательность сразу - не только в LINQ to SQL. Если вы хотите, чтобы это прекрасно, но это не всегда уместно.

Лично я постараюсь не объявлять, что вы возвращаете List<T> напрямую - обычно IList<T> более уместно и позволяет впоследствии перейти на другую реализацию. Конечно, есть некоторые операции, которые указаны только на List<T>... такое решение всегда сложно.

EDIT: (Я бы поставил это в комментарии, но это было бы слишком громоздким.) Отложенное выполнение позволяет вам иметь дело с источниками данных, которые слишком велики для размещения в памяти. Например, если вы обрабатываете файлы журналов - преобразовывая их из одного формата в другой, загружая их в базу данных, разрабатывая некоторые статистические данные или что-то в этом роде - вы вполне можете иметь возможность обрабатывать произвольные объемы данных, передавая их, но вы действительно не хотите всасывать все в память. Это может не беспокоить ваше конкретное приложение, но это что-то иметь в виду.

Ответ 2

У нас такой же сценарий - связь WCF с сервером, сервер использует LINQtoSQL.

Мы используем .ToArray() при запросе объектов с сервера, потому что это "незаконно" для клиента, чтобы изменить список. (Значит, нет никакой цели поддерживать ".Add", ".Remove" и т.д.).

Хотя я все еще на сервере, я бы рекомендовал оставить его по умолчанию (это не IEnumerable, а скорее IQueryable). Таким образом, если вы хотите отфильтровать еще больше на основе некоторых критериев, фильтрация будет STILL на стороне SQL до тех пор, пока не будет оценена.

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

Пример:

// This is just an example... imagine this is on the server only. It the
// basic method that gets the list of clients.
private IEnumerable<Client> GetClients()
{
    var result = MyDataContext.Clients;  

    return result.AsEnumerable();
}

// This method here is actually called by the user...
public Client[] GetClientsForLoggedInUser()
{
    var clients = GetClients().Where(client=> client.Owner == currentUser);

    return clients.ToArray();
}

Вы видите, что происходит там? Метод "GetClients" заставит загрузить ВСЕ "клиенты" из базы данных... ТОГДА предложение Where в методе GetClientsForLoogedInUser будет отфильтровано.

Теперь обратите внимание на небольшое изменение:

private IQueryable<Client> GetClients()
{
    var result = MyDataContext.Clients;  

    return result.AsQueryable();
}

Теперь фактическая оценка не будет выполняться до тех пор, пока не будет вызван ".TorArray"... и SQL сделает фильтрацию. МНОГО БОЛЬШЕ!

Ответ 3

В случае Linq-to-Objects возвращение List<T> из функции не так хорошо, как возвращение IList<T>, как указывает ВОЗМОЖНЫЙ СКОРОСТЬ. Но часто вы все еще можете сделать лучше. Если вещь, которую вы возвращаете, должна быть неизменной, IList - это плохой выбор, потому что он приглашает вызывающего добавить или удалить вещи.

Например, иногда у вас есть метод или свойство, которое возвращает результат запроса Linq или использует yield return для ленивого создания списка, а затем вы понимаете, что было бы лучше сделать это в первый раз, когда вы вызывается, кэширует результат в List<T> и после этого возвращает кэшированную версию. То, что при возврате IList может быть плохой идеей, потому что вызывающий может изменить список в своих целях, что приведет к повреждению вашего кеша, делая их изменения видимыми для всех других вызывающих абонентов.

Лучше вернуть IEnumerable<T>, так что все, что у них есть, - это итерация вперед. И если вызывающему абоненту нужен быстрый случайный доступ, то есть они хотят, чтобы они могли использовать [] для доступа по индексу, они могут использовать ElementAt, который Linq определяет так, что он тихо нюхает для IList и использует это, если доступно, и если нет он делает немой линейный поиск.

Одна вещь, которую я использовал ToList for, - это когда у меня сложная система выражений Linq, смешанная с пользовательскими операторами, которые используют yield return для фильтрации или преобразования списков. Переход в отладчик может стать очень запутанным, поскольку он перескакивает вокруг ленивой оценки, поэтому я иногда временно добавляю ToList() в несколько мест, чтобы я мог легче следовать пути выполнения. (Хотя, если вещи, которые вы выполняете, имеют побочные эффекты, это может изменить смысл программы.)

Ответ 4

Это зависит от необходимости изменения коллекции. Мне нравится использовать Array, когда я знаю, что никто не собирается добавлять/удалять элементы. Я использую список, когда мне нужно сортировать/добавлять/удалять элементы. Но, как правило, я просто оставляю его как IEnumerable, насколько это возможно.

Ответ 5

Если вам не нужны дополнительные функции List < > , почему бы не просто использовать IQueryable < > ?!?!?! Самый низкий общий знаменатель - лучшее решение (особенно, когда вы видите ответ Тимоти).