Я что-то упускаю из LINQ?

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

Я имею в виду, я мог видеть выгоду использования SQL-подобных операторов на вещах, отличных от баз данных. Но если я хотел написать SQL, почему бы просто не написать SQL и не допустить его на C #? Что мне здесь не хватает?

21.08.2008 21:54:56
6 ОТВЕТОВ
РЕШЕНИЕ

LINQ не о SQL. LINQ о применении парадигм функционального программирования к объектам.

LINQ to SQL - это ORM, встроенный в основу LINQ, но LINQ - это гораздо больше. Я не использую LINQ to SQL, но все же использую LINQ.

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

Перед LINQ эти задачи требуют написания вложенного foreach, который повторяет маленький список один раз для каждого элемента в большом списке O (N * M) и занимает около 10 строк кода.

foreach (int number in list1)
{
    foreach (int number2 in list2)
    {
        if (number2 == number)
        {
            returnList.add(number2);
        }
    }
}

Используя LINQ, он делает то же самое в одной строке кода:

var results = list1.Intersect(list2);

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

40
21.08.2008 21:59:00
Это было хорошо, спасибо. Мне интересно, в ваших двух примерах кода версия LINQ будет быстрее, чем "оригинальная" версия?
Frank V 14.11.2008 18:10:50
LINQ не собирается волшебным образом использовать сложность времени из этой операции. Так что, да, это выглядит лучше, но если это оптимизировано, это только немного.
mmcdole 9.02.2009 00:48:07
Что приятно, потому что я ненавижу синтаксис выражения.
Instance Hunter 28.02.2009 05:57:59
Это, пожалуй, самая странная вещь, которую я видел. «О, давайте использовать LINQ, но вместо того, чтобы сделать мой код более читабельным для будущих разработчиков с помощью синтаксиса встроенного в c #, давайте продолжим и сделаем длинную цепочку вызовов функций! Здорово!»
RCIX 5.12.2009 09:13:30
@Derrick Turk: Достаточно верно, но тогда вы не можете использовать такие вещи, как yield returnили итераторные блоки :)
RCIX 22.04.2010 01:29:31

Дело в том, что LINQ интегрирует ваши запросы в ваш основной язык программирования, позволяя вашей IDE предоставлять вам некоторые средства (например, Intellisense и поддержку отладки), которых у вас не было бы, и позволяя компилятору проверять тип вашего SQL код (что невозможно при обычном строковом запросе).

2
21.08.2008 21:56:11
Но все же зачем вам писать SQL-код в LINQ? Как бы вы настроили его? Как сотрудник базы данных, я с вопросником. Я просто не понимаю, почему вы хотели бы сделать это с точки зрения базы данных. Запросы, которые я видел в LINQ, кажутся мне раздутыми.
HLGEM 5.12.2008 20:23:21
Если вы используете ORM ( любой ORM), запросы будут раздутыми. Если вы хотите использовать «голое железо», вы должны использовать SQL через ADO.NET (что всегда возможно в некоторых критических разделах кода, даже если вы в основном используете LINQ).
TheSmurf 10.12.2008 18:50:06
Другая причина использования linq заключается в том, что, как бы раздутым ни был запрос, у авторов движка SQL может быть меньший набор шаблонов запросов для внутренней настройки, что было бы неплохо.
Michael Haren 17.02.2009 20:52:21

Так что действительно, очень важно, что LINQ не имеет ничего общего с Linq to SQL. Речь идет об улучшениях, которые он внес в сам язык C #.

5
21.08.2008 22:18:05

LINQ - это не просто система ORM, как отметил Джонатан, она привносит множество функциональных элементов программирования в C #. И это позволяет вам делать много вещей из базы данных в обычном коде C #. Трудно объяснить, насколько невероятно мощным это может быть. Подумайте, насколько наличие надежных, хорошо спроектированных общих структур данных (таких как список, стек, словарь / хэш и т. Д.), Включенных в общие структуры, улучшило состояние разработки в современных языках. Именно потому, что использование этих структур данных очень распространено, и сокращение интеллектуальных издержек при их использовании является огромным преимуществом. LINQ не делает ничего, что вы не можете сделать сами, но делает многие операции намного проще и проще.

Рассмотрим проверенный временем пример удаления дубликатов из неупорядоченного списка. В языке более низкого уровня, таком как C или C ++, вам, вероятно, придется сортировать список и поддерживать два индекса в списке, когда вы удаляете дубликаты. В языке с хешами (Java, C #, Javascript, Perl и т. Д.) Вы можете создать хеш, в котором ключи являются уникальными значениями, а затем извлечь ключи в новый список. С LINQ вы можете просто сделать это:

int[] data = { 0, 1, 3, 3, 7, 8, 0, 9, 2, 1 };

var uniqueData = data.GroupBy(i => i).Select(g => g.Key);
5
21.08.2008 23:20:41
Или даже лучше: data.Distinct ();
Nathan Baulch 1.12.2008 17:42:38

Перед:

// Init Movie
m_ImageArray = new Image[K_NB_IMAGE];

Stream l_ImageStream = null;
Bitmap l_Bitmap = null;

// get a reference to the current assembly
Assembly l_Assembly = Assembly.GetExecutingAssembly();

// get a list of resource names from the manifest
string[] l_ResourceName = l_Assembly.GetManifestResourceNames();

foreach (string l_Str in l_ResourceName)
{
    if (l_Str.EndsWith(".png"))
    {
        // attach to stream to the resource in the manifest
        l_ImageStream = l_Assembly.GetManifestResourceStream(l_Str);
        if (!(null == l_ImageStream))
        {
            // create a new bitmap from this stream and 
            // add it to the arraylist
            l_Bitmap = Bitmap.FromStream(l_ImageStream) as Bitmap;
            if (!(null == l_Bitmap))
            {
                int l_Index = Convert.ToInt32(l_Str.Substring(l_Str.Length - 6, 2));
                l_Index -= 1;
                if (l_Index < 0) l_Index = 0;
                if (l_Index > K_NB_IMAGE) l_Index = K_NB_IMAGE;
                m_ImageArray[l_Index] = l_Bitmap;
            }
            l_Bitmap = null;
            l_ImageStream.Close();
            l_ImageStream = null;
        } // if
    } // if
} // foreach

После:

Assembly l_Assembly = Assembly.GetExecutingAssembly();

//Linq is the tops
m_ImageList = l_Assembly.GetManifestResourceNames()
    .Where(a => a.EndsWith(".png"))
    .OrderBy(b => b)
    .Select(c => l_Assembly.GetManifestResourceStream(c))
    .Where(d => d != null)  //ImageStream not null
    .Select(e => Bitmap.FromStream(e))
    .Where(f => f != null)  //Bitmap not null
    .ToList();

Или, альтернативно ( синтаксис запроса ):

Assembly l_Assembly = Assembly.GetExecutingAssembly();

//Linq is the tops
m_ImageList = (
    from resource in l_Assembly.GetManifestResourceNames()
    where resource.EndsWith(".png")
    orderby resource
    let imageStream = l_Assembly.GetManifestResourceStream(resource)
    where imageStream != null
    let bitmap = Bitmap.FromStream(imageStream)
    where bitmap != null)
    .ToList();
20
7.06.2010 04:46:50
Образец before более многословен, но имеет то преимущество, что может быть отлаживаемым. Может быть трудно анализировать и исправлять сложные операторы linq, потому что они так сильно скрывают от разработчика.
Phil Gan 7.06.2010 15:24:20
@Phil, да и нет, чем больше у вас строк кода, тем больше и отладки! Сказав это, именно поэтому я предпочитаю синтаксис метода (первый из примеров после), потому что легко разбить цепочку методов на две в любой точке.
Benjol 8.06.2010 04:41:00
@Benjol: я никогда не думал об этом ... Так что вы можете разбить длинную инструкцию linq, чтобы увидеть, что возвращает каждый метод, или объединить несколько коротких операторов linq в одну, когда вы убедились, что они работают так, как вы ожидаете. Это интересно!
Phil Gan 8.06.2010 08:12:14
В предыдущей версии вы явно закрываете каждый поток изображений. Это происходит под капотом в версии LINQ?
I. J. Kennedy 24.06.2010 19:35:33
@Я. J, хороший вопрос. Я думаю, что это ошибка в моем коде. Linq делает много волшебных вещей, но я не думаю, что это заходит так далеко. Это, вероятно, стоит другого вопроса на самом деле ... (может быть, здесь ?: stackoverflow.com/questions/1751153/… )
Benjol 25.06.2010 05:32:08

Поскольку linq - это действительно монады в SQL-одежде, я использую его в проекте для выполнения асинхронных веб-запросов с помощью монады продолжения, и это доказывает свою эффективность!

Проверьте эти статьи: http://www.aboutcode.net/2008/01/14/Async+WebRequest+Using+LINQ+Syntax.aspx http://blogs.msdn.com/wesdyer/archive/2008/01/ 11 /-чудесами-оф-monads.aspx

Из первой статьи:

    var requests = new[] 
    {
        WebRequest.Create("http://www.google.com/"),
        WebRequest.Create("http://www.yahoo.com/"),
        WebRequest.Create("http://channel9.msdn.com/")
    };

    var pages = from request in requests
                select
                    from response in request.GetResponseAsync()
                    let stream = response.GetResponseStream()
                    from html in stream.ReadToEndAsync()
                    select new { html, response };

    foreach (var page in pages)
    {
        page(d =>
        {
            Console.WriteLine(d.response.ResponseUri.ToString());
            Console.WriteLine(d.html.Substring(0, 40));
            Console.WriteLine();
        });
    }
4
13.03.2009 03:02:26