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

Когда следует использовать LINQ для С#?

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

Любые личные впечатления/предложения, которые вы можете пожелать поделиться?

Спасибо!

4b9b3361

Ответ 1

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

Вот небольшой фрагмент, который я написал для вспомогательного класса Active Directory, который определяет, является ли конкретный пользователь определенной группой. Обратите внимание на использование метода Any() для итерации по группам полномочий пользователя до тех пор, пока не найдет один с соответствующим SID. Более чистый код, чем альтернатива.

private bool IsInGroup( GroupPrincipal group, UserPrincipal user )
{
    if (group == null || group.Sid == null)
    {
        return false;
    }
    return user.GetAuthorizationGroups()
               .Any( g => g.Sid != null && g.Sid.CompareTo( group.Sid ) == 0 );
}

Альтернатива:

private bool IsInGroup( GroupPrincipal group, UserPrincipal user )
{
    if (group == null || group.Sid == null)
    {
        return false;
    }
    bool inGroup = false;
    foreach (var g in user.GetAuthorizationGroups())
    {
         if ( g => g.Sid != null && g.Sid.CompareTo( group.Sid ) == 0 )
         {
            inGroup = true;
            break;
         }
    }
    return inGroup;
}

или

private bool IsInGroup( GroupPrincipal group, UserPrincipal user )
{
    if (group == null || group.Sid == null)
    {
        return false;
    }

    foreach (var g in user.GetAuthorizationGroups())
    {
         if ( g => g.Sid != null && g.Sid.CompareTo( group.Sid ) == 0 )
         {
            return true;
         }
    }
    return false;
}

Здесь фрагмент, который выполняет поиск по репозиторию, заказывает и преобразует первые 10 подходящих бизнес-объектов в определенную для просмотра модель (Distance - это расстояние редактирования Левенштейна от уникального идентификатора уникальной модели от уникального параметра).

model.Results = this.Repository.FindGuestByUniqueID( uniqueID, withExpired )
                               .OrderBy( g => g.Distance )
                               .Take( 10 )
                               .ToList()
                               .Select( g => new GuestGridModel( g ) );

Ответ 2

Это зависит от того, какой тип linq вы имеете в виду.

Это linq-to-sql? В этом случае это орм со всеми теми же преимуществами, которые исходят от использования любого другого орма. Я не использую его много и не могу сказать больше.

Это linq-to-objects? В этом случае вы действительно говорите о наборе других вещей: методах расширения, ленивых итераторах и синтаксисе понимания запроса. Это введение в мир функционального программирования. У меня мало пользы для синтаксиса понимания запроса, но для остальных я могу лучше продемонстрировать пример.

Скажем, вы хотите прочитать файл в строковой последовательности. Для каждой строки вы хотите проверить, соответствует ли она некоторым критериям, преобразовать часть этих строк в целое число и суммировать первые 10 из этих целых чисел, которые также находятся в определенном диапазоне. Здесь старый способ, которым вы это сделаете:

int SumXValues(string filename)
{
    string line;
    int sum = 0;
    int count = 0;
    using (var rdr = new StreamReader(filename))
    {

        while ( (line = rdr.ReadLine()) != null && count < 10)
        {
           int val;
           if (int.TryParse(line.Substring(3,3))
           {
               if (val > 4 && val < 25)
               {
                    sum += val;
                    count ++;
               }
            }
        }
    }
    return sum;
}

Здесь новый способ:

IEnumerable<string> ReadLines(string filename)
{
    string line;
    using (var rdr = new StreamReader(filename))
        while ( (line = rdr.ReadLine()) != null)
           yield return line;
}

int SumXValues(string filename)
{
    return ReadLines(filename)
               .Select(l => l.Substring(3,3))
               .Where(l => int.TryParse(l))
               .Select(i => int.Parse(i))
               .Where(i => i > 4 && i < 16)
               .Take(10)
               .Sum(i => i);
}

Обратите внимание, что новый код на самом деле короче. Но почему это также лучше? Есть (по крайней мере) 4 причины:

  • Надеюсь, это очевидно, как можно использовать функцию readlines. Вы также можете указать на то, что этот стиль поможет вам повторно использовать больше кода.
  • Он масштабируется лучше. Обратите внимание на все цепочки вызовов функций в этой последней функции. Вы знаете, сколько раз этот код будет итератором над строками в вашем файле? Точно один раз! На самом деле даже не так долго, как он перестанет читать из файла после взятия первых 10 предметов. И если вы измените его, чтобы вернуть перечислимый, а затем использовать его в другом месте с другими методами расширения? Еще раз! Это позволяет создавать, смешивать и повторно смешивать результаты запроса во время выполнения без дорогостоящих дополнительных проходов в ваших списках.
  • Это более удобно. Если критерии изменяются, легко определить точное "правило" (если хотите), которое вам нужно, и изменить только эту часть.
  • Это более читаемо. Это позволяет вам выражать код в терминах того, что он делает, а не как он это делает.

Ответ 3

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

var circles =
        from s in allShapes
        where s.Type == ShapeTypes.Circle
        select s;

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

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

Ответ 4

В книге Essential LINQ содержится замечание о преимуществах LINQ:

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

Ответ 5

Вы правы, редко бывает сложно воспроизвести функции на регулярной С#. Это то, что они называют синтаксическим сахаром. Это просто удобство. Вы знаете об автоматических свойствах? Те, которые позволяют писать public class User { public int Id { get; set; } }, очень легко реплицируются в "обычный" код С#. Тем не менее, автоматические свойства по-прежнему удивительны;)

Фильтрация и сортировка - это в значительной степени ядро ​​LINQ. У вас есть список пользователей, называемых, ну, users, и вы хотите найти тех, кто вошел в систему сегодня, и отобразить их в порядке последнего входа. Перед LINQ вы, вероятно, сделаете что-то вроде создайте новый список, который вы заполняете на основе исходного списка, путем его повторения, добавления того, что соответствует критериям, и затем реализации своего рода IComparable. Теперь вы можете просто сделать:

users = users.Where(u => u.LastLoggedIn.Date = DateTime.Today)
             .OrderBy(u => u.LastLoggedIn).ToList();

Удобство =)

Ответ 6

Я использую LINQ для DataSet для работы с DataTables. Таблицы данных - это общие хранилища данных, в которых я часто храню значения, например. из загруженного CSV файла. Гораздо читабельнее и удобнее использовать LINQ для запроса или объединения данных вместо "грубой силы" с помощью for-loops.

Ответ 7

Я бы поставил вопрос: можете ли вы показать нам, как бы вы могли эмулировать функции Linq без него? У меня возникли проблемы с рассмотрением случая, когда это не огромная помощь.

Например, я недавно увидел что-то подобное:

foreach (var person in people.OrderBy(p => p.Company)
                             .ThenBy(p => p.LastName)
                             .ThenBy(p => p.FirstName)) {
    ...
}

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

Ответ 8

Да, вы можете легко использовать LINQ для объектов, используя альтернативный код, и это не сложно. Мне нравится семантика лямбда-выражений, и она превращает несколько строк кода в один. Но многие операции, которые вы можете делать с вашим собственным кодом, кроме некоторых более крупных операций (объединение, пересечение и т.д.), Легче выполнять с LINQ.

LINQ имеет другие вкусы; LINQ to XML отлично справляется с работой с данными XML. Мне действительно нравится это лучше, чем предыдущие доступные объекты.

LINQ to SQL и ADO.NET Entity Framework (с LINQ to Entities) являются объектно-реляционным mapper и могут отображаться в ваших таблицах базы данных и действовать как хранимые процедуры и наборы данных ADO.NET, так что это очень хорошая альтернатива чем слабые наборы данных /datatables, и мне тоже нравится слишком типизированные наборы данных/таблицы.

НТН.

Ответ 9

Посмотрите на любой из многих ответов, которые Джон Скит предоставляет на вопросы Linq, и вы увидите, насколько действительно универсальный и полезный Linq.

https://stackoverflow.com/search?q=user:22656+ [linq]

Ответ 10

Взгляните на ReSharper, если вы еще этого не сделали. В нем есть много подсказок для "... конвертировать в синтаксис LINQ", поэтому он может показать вам кое-что, что вы не учли при обучении.:)

Ответ 11

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

Один из способов использования LINQ - написать тестовый код оракула. Очень важно, чтобы тестовый код был простым и максимально приближенным к "явно правильному", или же он будет содержать столько ошибок, сколько кода, который он должен тестировать. С одной конкретной особенностью, которую я тестирую сейчас, я написал небольшой список наборов, которые точно описывают, как я ожидаю, что функция будет работать. Благодаря LINQ преобразование этих понятий в код становится тривиально простым:

A = all items
B = [x in A: x.Type = selectedtype, x.Source = "sourceA"]
C = [x in A: x.Source = "sourceB"]
D = B union C

В коде:

IEnumerable<MyClass> SetB(IEnumerable<MyClass> allItems, MyType type)
{
  var result = from item in allItems
               where item.Type == type && item.Source == "sourceA"
               select item;
  return result;
}

IEnumerable<MyClass> SetC(IEnumerable<MyClass> allItems)
{
  var result = from item in allItems
               where item.Source == "sourceB"
               select item;
  return result;
}

IEnumerable<MyClass> SetD(IEnumerable<MyClass> allItems, MyType type)
{
  var setB = SetB(allItems, type);
  var setC = SetC(allItems);
  return setB.Union(setC);
}

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

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

Ответ 12

Для меня я использую его только для доступа к базам данных. Я почти никогда не запрашиваю XML или список.

Ответ 13

Мне представляется полезным преобразовать/ "проектировать" данные, прежде чем привязывать их к сетке для целей только для чтения.

Ответ 14

Набор функций языка LINQ не так легко копируется в коде С# 2.0, без методов расширения, лямбда-выражений и даже без операторов запроса. Весь смысл LINQ в том, что у вас есть встроенная версия запросов, в которой вы используете компилятор для проверки их работоспособности. Другим важным моментом является унификация представления в разных источниках данных, будь то база данных или сбор данных в памяти. Вы можете жить без LINQ, так же, как вы можете жить без какой-либо другой функции языка и кода в Assembler, но есть очевидные преимущества, которые трудно контролировать;)

Ответ 15

Еще один момент, чтобы добавить ко всему, что является своего рода итоговой точкой. Вы можете видеть сверху, что он используется для удобства и лаконичности и может использоваться с коллекциями, SQL, XML (и все, что нужно для реализации LINQ-провайдера), но лучше всего вам нужно только изучить синтаксис LINQ один раз и переносится на все эти полезные технологические области.