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

Где рисовать линию - возможно ли любить LINQ слишком много?

Недавно я нашел LINQ и люблю его. Я нахожу много случаев, когда использование его гораздо более выразительно, чем версия с длинным ружьем, но коллега передал комментарий о том, что я злоупотребляю этой технологией, которая теперь меня второй угадывает. Я считаю, что если технология работает эффективно и код элегантный, то почему бы не использовать его? Это неправильно? Я мог потратить дополнительное время на процесс обработки "longhand", и в то время как полученный код может быть на несколько миллисекунд быстрее, он в 2-3 раза больше кода и, следовательно, в 2-3 раза больше шансов, что могут быть ошибки.

Я считаю, что неправильно? Должен ли я писать свой код из рук в руки, а не с помощью LINQ? Разве это не LINK?

Изменить: я говорил о LINQ для объектов, я не использую LINQ для XML так сильно, и я использовал LINQ to SQL, но я не так влюблен в эти ароматы как LINQ для объектов.

4b9b3361

Ответ 1

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

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

Ответ 2

Да, вы можете любить LINQ слишком много - Одиночный оператор LINQ RayTracer

Где вы рисуете линию? Я бы сказал, использую LINQ столько, сколько он делает код более простым и понятным для чтения.

В тот момент, когда версия LINQ становится более трудной для понимания, тогда версия, отличная от LINQ, для обмена, и наоборот. EDIT: в основном это относится к LINQ-To-Objects, поскольку другие отличия LINQ имеют свои преимущества.

Ответ 3

Невозможно любить Linq для объектов слишком много, это потрясающая технология!

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

Ответ 4

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

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

Ответ 5

Это такие случаи, когда важно запомнить золотые правила оптимизации:

  • Не делай этого
  • Для экспертов: не делайте этого еще

Вы должны абсолютно не беспокоиться о "злоупотреблении" linq, если вы не можете явно указать его как причину проблемы с производительностью

Ответ 6

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

var v = List.Where(...);
for(int i = 0; i < v.Count(); i++)
{...}

и понять, как работает расписание выполнения, то, скорее всего, это будет не так много медленнее, чем путь вперед. Согласно Андерсу Хейлсбергу (архитектор С#), компилятор С# не особенно хорош в оптимизации циклов, однако он намного лучше оптимизирует и распараллеливает деревья выражений. Со временем это может быть более эффективным, чем цикл. Версия List < > ForEach выполняется так же быстро, как цикл for, хотя я не могу найти ссылку, которая доказывает это.

P.S. Мой личный фаворит - ForEach < > менее известный кузен IndexedForEach (используя методы расширения)

List.IndexedForEach( (p,i) => 
 {
     if(i != 3)
        p.DoSomething(i);
 };

Ответ 7

LINQ может быть как искусство. Продолжайте использовать его, чтобы сделать код красивым.

Ответ 8

Вы отвечаете на свой вопрос, говоря о написании в 2-3 раза больше кода за несколько мсек производительности. Я имею в виду, если ваша проблемная область требует ускорения, то да, если нет, вероятно, нет. Однако, действительно ли это всего лишь несколько мс производительности или это > 5% или > 10%. Это оценочное суждение, основанное на индивидуальном случае.

Ответ 9

Где рисовать линию?

Ну, мы уже знаем, что плохая идея реализовать свою собственную quicksort в linq, по крайней мере, по сравнению с использованием только порядка linq orderby.

Ответ 10

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

Ответ 11

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

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

Ответ 12

Моя единственная забота о LINQ заключается в ее реализации объединений.

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

Добавление соединения к запросу LINQ по существу превращает алгоритм линейного времени в алгоритм с квадратичным временем. Даже если вы считаете, что преждевременная оптимизация является корнем всего зла, скачок от O (n) до O (n ^ 2) должен дать вам паузу. (Это O (n ^ 3), если вы также присоединяетесь к объединенному элементу в другую коллекцию.)

Относительно легко обойти это. Например, этот запрос:

var list = from pr in parentTable.AsEnumerable()
join cr in childTable.AsEnumerable() on cr.Field<int>("ParentID") equals pr.Field<int>("ID")
where pr.Field<string>("Value") == "foo"
select cr;

аналогичен тому, как вы присоединяетесь к двум таблицам в SQL Server. Но это ужасно неэффективно в LINQ: для каждой родительской строки, возвращаемой предложением where, запрос сканирует всю дочернюю таблицу. (Даже если вы присоединяетесь к неиндексированному полю, SQL Server будет строить хеш-таблицу, чтобы ускорить соединение, если это возможно. Это немного за пределами класса оплаты LINQ.)

Этот запрос, однако:

string fk = "FK_ChildTable_ParentTable";
var list = from cr in childTable.AsEnumerable()
where cr.GetParentRow(fk).Field<string>("Value") == "foo"
select cr;

дает тот же результат, но только один раз сканирует дочернюю таблицу.

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

Dictionary<Foo, Bar> map = buildMap(foos, bars);
var list = from Foo f in foos
where map[f].baz == "bat"
select f;