Опубликован: 01.11.2011 | Доступ: свободный | Студентов: 1424 / 62 | Оценка: 3.84 / 3.44 | Длительность: 15:38:00
Специальности: Программист
Лекция 4:

Многопоточность, язык интегрированных запросов LINQ

Аннотация: В данной лекции мы поговорим о методах создания высокопроизводительных приложений. Будут освещены такие вопросы, как многопоточность в C# и .Net, запуск потоков, передача данных новым потокам, асинхронные вызовы методов, завершение потоков, синхронизация работы между потоками, события, параллельное программирование. Соотношение императивных и функциональных языков. Выражения запросов. Стандартные операции запросов. Ключевые слова запросов C#: from, join, where, orderby, select, let, group, into.

Дополнительные материалы к занятию можно скачать здесь.

Вложенные файлы: Presentation_4.pptx

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

Существует альтернативный подход разработки программного обеспечения. Он называется функциональным программированием. Процитируем Лоренса Паулсона: "Функциональное программирование ставит своей целью придать каждой программе простую математическую интерпретацию. Эта интерпретация должна быть независима от деталей исполнения и понятна людям, которые не имеют научной степени в предметной области"[14].

В качестве примера можно привести язык структурированных запросов (SQL). При разработке запросов в SQL программисту не требуется знать тип извлекаемых данных, как, например, в С++, производительность труда разработчика при этом выше. К функциональным языкам относятся такие программные продукты, как: Lisp, ISWIM, Scheme, ML, Caml, Miranda, Haskell, Gofer, Clean и другие. С помощью функциональных языков можно разрабатывать короткие понятные программы. Сравним алгоритм нахождения суммы ряда от 1 до 10, написанный на С++ и на языке Haskell.

С++: Haskell:
int sum = 0;
 for (int i = 1; i <= 10; i++)
 {
     sum += i;
 }
        
sum [1..10]
        

В С# реализованы возможности функциональных языков в технологии LINQ. Аббревиатура LINQ (Language-Integrated Query) обозначает язык интегрированных запросов. При этом можно создавать запросы на подобие SQL-ных конструкций. LINQ позволяет извлекать информацию из различных источников данных. В основу LINQ положено понятие запроса, в котором определяется информация получаемая из источника данных. После формирования запроса происходит его выполнение. Выполнение осуществляется в цикле foreach. В результате выполнения запроса получаются некие результаты. При формировании запроса указывается что необходимо извлечь из источника данных, а при выполнении запроса выводятся конкретные результаты [15].

Рассмотрим применение технологии LINQ на примере массивов. Ниже показано, как с помощью языка интегрированных запросов можно извлечь четные числа из массива.

using System;
using System.Linq;

    class Example
    {
        static void Main()
        {
            int[] myArray = {-18, 15, -4, 69, 36, 11, 98, -7, -8};
            var criteria = from n in myArray
                          where n % 2 == 0
                          select n;
            Console.Write("Четные значения из массива myArray: \n");
            foreach (int i in criteria) Console.Write(i + " ");
            Console.WriteLine();
            Console.WriteLine("Нажмите любую кнопку!");
            Console.ReadKey();
        }
    }
    

Результат:


Переменная criteria является переменной запроса. Благодаря ключевому слову var переменная criteria становится неявно типизированной. Запросы начинаются с оператора from, определяющего два элемента. Первым элементом является переменная диапазона, принимающая элементы из источника данных (нашем случае это - переменная n). Вторым элементом является источник данных (в нашем случае - это массив myArray). Тип переменной диапазона выводится из источника данных. Поэтому переменная n является целочисленной.

Обобщенный синтаксис оператора from:

from переменная диапазона in источник данных
where критерий отбора
    

Запросы оканчиваются оператором select или group.

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

foreach (int i in criteria) Console.Write(i + " ");
    

При разработке запросов используются следующие ключевые слова:

Ascending, by , descending, equals, from, group, in, into, join, let, on, orderby, select, where
    

В запросе может быть несколько операторов where. В следующем примере мы отберем элементы массива, кратные трем, но меньше 50.

using System;
using System.Linq;

class Example
{
    static void Main()
    {
        int[] myArray = { -18, 15, -4, 69, 36, 11, 98, -7, -8 , 2, 7,-6,14};
        var criteria = from n in myArray
                       where n % 3 == 0
                       where n < 50
                       select n;
        Console.Write("Числа, кратные трем, меньше 50: \n");
        foreach (int i in criteria) Console.Write(i + " ");
        Console.WriteLine();
        Console.WriteLine("Нажмите любую кнопку!");
        Console.ReadKey();
    }
}
    

Результат можно упорядочить по возрастанию:

using System;
using System.Linq;

class Example
{
    static void Main()
    {
        int[] myArray = { -18, 15, -4, 69, 36, 11, 98, -7, -8 , 2, 7,-6,14};
        var criteria = from n in myArray
                       where n % 3 == 0
                       where n < 50
                       orderby n
                       select n;
        Console.Write("Числа, кратные трем, меньше 50, упорядоченные по возрастанию: \n");
        foreach (int i in criteria) Console.Write(i + " ");
        Console.WriteLine();
        Console.WriteLine("Нажмите любую кнопку!");
        Console.ReadKey();
    }
}
    

Или по убыванию:

using System;
using System.Linq;

class Example
{
    static void Main()
    {
        int[] myArray = { -18, 15, -4, 69, 36, 11, 98, -7, -8 , 2, 7,-6,14};
        var criteria = from n in myArray
                       where n % 3 == 0
                       where n < 50
                       orderby n descending
                       select n;
        Console.Write("Числа, кратные трем, меньше 50, упорядоченные по убыванию: \n");
        foreach (int i in criteria) Console.Write(i + " ");
        Console.WriteLine();
        Console.WriteLine("Нажмите любую кнопку!");
        Console.ReadKey();
    }
}
    

В критерии отбора допускается использование логических условий, таких как && - конъюнкция, или || - дизъюнкция.

using System;
using System.Linq;

class Example
{
    static void Main()
    {
        int[] myArray = {-8,3,16,-4,71,83,2,9,32,7,-5,-3};
        var criteria = from n in myArray
                       where n >3 && n <20
                       orderby n 
                       select n;
        Console.Write("Числа больше 3, но меньше 20, упорядоченные по возрастанию: \n");
        foreach (int i in criteria) Console.Write(i + " ");
        Console.WriteLine();
        Console.WriteLine("Нажмите любую кнопку!");
        Console.ReadKey();
    }
}
    

Ниже мы покажем, каким образом можно отделить русские сайты от других сайтов

using System;
using System.Linq;

class Example
{
    static void Main()
    {
        string[] domens = {"www.google.com","www.cia.gov","www.un.org","www.mail.ru","www.yandex.ru",
   "www.fbi.gov","www.microsoft.com","www.ibm.com"};
        var netAddrs = from addr in domens
                       where addr.EndsWith(".ru", StringComparison.Ordinal)
                       select addr;

        foreach (var str in netAddrs) Console.WriteLine(str);
        Console.WriteLine("Нажмите любую кнопку!");
        Console.ReadKey();
    }
}
    

Можно осуществлять сортировку по нескольким критериям одновременно. Ниже приводится пример сортировки некоего прайс-листа.

using System;
using System.Linq;

class Goods
{
    public string   ProductName {get; private set;}  //Название товара
    public string   Description {get; private set;}  //Описание товара
    public double   Price       {get; private set;}  //Цена товара
    public string   Manufacturer {get; private set;} //Страна-Производитель
    public DateTime ExpireDate  {get; private set;}  //Срок годности

    public Goods(string pn,string ds, double pr, string mn, DateTime exp)
    {
        ProductName = pn;
        Description = ds;
        Price = pr;
        Manufacturer = mn;
        ExpireDate = exp;
    }
}

class OrderbyAscending
{
    static void Main()
    {
        Goods[] Product = {
                              new Goods("Сахар","Сладкий порошок", 25, "Куба", new DateTime(2011, 3, 1, 0, 0, 0)),
                              new Goods("Молоко","Белая жидкость", 30, "Россия", new DateTime(2011, 5, 2, 0, 0, 0)),
                              new Goods("Апельсины","Вкусные плоды", 50, "Морокко", new DateTime(2011, 5, 10, 0, 0, 0)),
                              new Goods("Лимоны","Кислые плоды", 80, "Израиль", new DateTime(2011, 6, 10, 0, 0, 0)),
                             };
        var prdInfo = from prd in Product
                      orderby prd.ProductName, prd.Description, prd.Price, prd.ExpireDate
                      select prd;
        Console.WriteLine("Прайс-лист в отсортированном порядке: ");
        string str = "";

        foreach (Goods prd in prdInfo)
        {
            if (str != prd.ProductName)
            {
                Console.WriteLine();
                str = prd.ProductName;
            }

            Console.WriteLine("{0} - {1}\t, {2}, {3,10:c} {4}", prd.ProductName, 
    prd.Description, prd.Manufacturer, prd.Price, prd.ExpireDate);
        }
        Console.WriteLine();
        Console.WriteLine("Нажмите любую кнопку!");
        Console.ReadKey();
    }
}
    
Листинг .