Типичные ошибки / ошибки в Linq / Standard Query Operator? - PullRequest
3 голосов
/ 13 сентября 2010

Для программистов, которые не имеют опыта функционального программирования, есть ли ошибки, которых следует избегать?

Ответы [ 4 ]

11 голосов
/ 13 сентября 2010

Самая большая ошибка, которую обычно делают люди, заключается в неправильном понимании правил лени и оценки для запроса LINQ:

Запросы ленивы: они не выполняются, пока вы не выполните итерации по ним:

// This does nothing! No query executed!
var matches = results.Where(i => i.Foo == 42);

// Iterating them will actually do the query.
foreach (var match in matches) { ... }

Кроме того, результаты не кэшируются.Они вычисляются при каждой итерации по ним:

var matches = results.Where(i => i.ExpensiveOperation() == true);

// This will perform ExpensiveOperation on each element.
foreach (var match in matches) { ... }

// This will perform ExpensiveOperation on each element again!
foreach (var match in matches) { ... }

Итог: узнайте, когда ваши запросы будут выполнены.

4 голосов
/ 14 сентября 2010

Для программистов, которые не имеют опыта функционального программирования, есть ли ошибки, которых следует избегать?

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

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

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

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

int number; 
from s in strings let b = Int32.TryParse(s, out number) blah blah blah

Это просто требует мира боли, потому что TryParse изменяет значение переменной, которая находится за пределами запроса.

В этом конкретном случае вам лучше сделать

int? MyParse(string s) 
{ 
    int result;
    return Int32.TryParse(s, out result) ? (int?)result : (int?)null;
}
...
from s in strings let number = MyParse(s) where number != null blah blah blah...
3 голосов
/ 14 сентября 2010

Понимание семантики замыканий .

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

Хотя замыкания очень полезны, они также могут вводить в заблуждение и приводить к слегка некорректному коду.Тот факт, что замыкания являются «живыми» (что означает, что изменения в переменных вне захваченного выражения видны выражению) также неожиданен для некоторых разработчиков.

Вот пример, когда замыкания создают проблемы для запросов LINQ.Здесь использование замыканий и отложенного выполнения объединяются для создания неверных результатов:

// set the customer ID and define the first query
int customerID = 12345;
var productsForFirstCustomer = from o in Orders
                               where o.CustomerID = customerID
                               select o.ProductID;

// change customer ID and compose another query...
customerID = 56789; // change the customer ID...
var productsForSecondCustomer = from o in Orders
                                where o.CustomerID = customerID
                                select o.ProductID;

if( productsForFirstCustomer.Any( productsForSecondCustomer ) )
{
   // ... this code will always execute due to the error above ...
}

Этот запрос всегда будет вводить тело оператора if() { }, поскольку при изменении значения customerID он влияет на выполнениеоба запроса - фактически оба используют один и тот же идентификатор, поскольку переменная customerID фиксируется в обоих операторах LINQ .

3 голосов
/ 13 сентября 2010

IMO, когда вы сталкиваетесь с LINQ, вы должны знать эти темы (они являются большими источниками ошибок):

Отсроченное выполнение (по SO)

Закрытие (по SO - 1)

Закрытие (на SO - 2)

Закрытие (блог Эрика Липперта)

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