Вы выбираете Linq вместо Forloops? - PullRequest
2 голосов
/ 26 июля 2010

Учитывая данные, содержащие два столбца, как это:

Private Function CreateDataTable() As DataTable
    Dim customerTable As New DataTable("Customers")
    customerTable.Columns.Add(New DataColumn("Id", GetType(System.Int32)))
    customerTable.Columns.Add(New DataColumn("Name", GetType(System.String)))

    Dim row1 = customerTable.NewRow()
    row1.Item("Id") = 1
    row1.Item("Name") = "Customer 1"
    customerTable.Rows.Add(row1)

    Dim row2 = customerTable.NewRow()
    row2.Item("Id") = 2
    row2.Item("Name") = "Customer 2"
    customerTable.Rows.Add(row2)

    Dim row3 = customerTable.NewRow()
    row3.Item("Id") = 3
    row3.Item("Name") = "Customer 3"
    customerTable.Rows.Add(row3)

    Return customerTable
End Function

Использовали бы этот фрагмент для получения списка (целого числа), содержащего все идентификаторы:

Dim table = CreateDataTable()

Dim list1 As New List(Of Integer)

For i As Integer = 0 To table.Rows.Count - 1
    list1.Add(CType(table.Rows(i)("Id"), Integer))
Next

Вернее, этот:

Dim list2 = (From r In table.AsEnumerable _
             Select r.Field(Of Integer)("Id")).ToList()

Это не вопрос о том, следует ли типизировать приведение столбца Id к Integer, используя .Field (Of Integer), CType, CInt, DirectCast или что-то еще, но обычно о том, выбираете ли вы Linq вместо forloops, как предполагает субъект.


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

график http://dnlmpq.blu.livefilestore.com/y1pOeqhqQ5neNRMs8YpLRlb_l8IS_sQYswJkg17q8i1K3SjTjgsE4O97Re_idshf2BxhpGdgHTD2aWNKjyVKWrQmB0J1FffQoWh/analysis.png?psid=1

На вертикальной оси показаны миллисекунды, которые потребовался коду для преобразования идентификаторов строк в общий список с количеством строк, показанных на горизонтальной оси. Синяя линия является результатом императивного подхода (forloop), красная линия - декларативным кодом (linq).


Какой бы путь вы обычно не выбирали: почему вы идете этим путем, а не другим?

Ответы [ 7 ]

5 голосов
/ 26 июля 2010

По возможности я предпочитаю декларативный способ программирования, а не императив.Когда вы используете декларативный подход, CLR может оптимизировать код на основе характеристик машины.Например, если он имеет несколько ядер, он может распараллелить выполнение, а если вы используете императивный цикл for, вы в основном блокируете эту возможность.Сегодня, возможно, нет большой разницы, но я думаю, что в будущем появится все больше и больше расширений, таких как PLINQ, позволяющих улучшить оптимизацию.

1 голос
/ 26 июля 2010

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

Большинство проблем с производительностью на самом деле не сравнимы с читабельностью для меня.

Ясность превосходит ум.

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

1 голос
/ 26 июля 2010

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

1 голос
/ 26 июля 2010

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

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

0 голосов
/ 28 июля 2010

Я стараюсь следовать этим правилам:

  • Всякий раз, когда я просто запрашиваю (фильтрую, проецирую, ...) коллекции, использую LINQ.
  • Как только я на самом деле что-то делаю с результатом (т. Е. Вводит побочные эффекты), я использую цикл for.

Так что в этом примере я буду использовать LINQ.

Кроме того, я всегда стараюсь отделить «определение запроса» от «оценки запроса»:

Dim query = From r In table.AsEnumerable() 
            Select r.Field(Of Integer)("Id")

Dim result = query.ToList()

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

0 голосов
/ 26 июля 2010

Я начал, но обнаружил, что в некоторых случаях я сэкономил время, используя этот подход:

for (var i = 0, len = list.Count; i < len; i++) { .. }

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

0 голосов
/ 26 июля 2010

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

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