LINQ: узагальнення і інтерфейси 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

LINQ: узагальнення і інтерфейси



Запити LINQ базуються на узагальненнях (generic), які вперше були представлені в.NET Framework версії 2.0.

Узагальнення (generic, універсальні типи) були додані в мову C# версії 2.0 і середовище CLR. Узагальнення в платформі.NET Framework представляють концепцію параметрів типів, які дозволяють розробляти класи і методи, що не дотримуються специфікації одного або декількох типів до тих пір, поки клас або метод не буде оголошений клієнтським кодом і доки не буде створений його екземпляр.

Призначення узагальнень - досягнення максимального рівня повторного використання коду, безпеки типу і продуктивності.

З узагальненням пов'язано поняття інтерфейсу, зокрема стандартного інтерфейсу IEnumerable<(Of <(T>)>)

 

Для написання запитів не потрібне глибоке знання узагальнень і інтерфейсів. Але розуміння двох основних понять може згодитися.

  • При створенні екземпляра класу універсальної колекції, наприклад List<(Of <(<T>)>), "T" замінюється типом об'єктів, які зберігатимуться в списку. Наприклад, список рядків виражається як List<string>, а список об'єктів Customer виражається як List<Customer>. Універсальний список є таким, що строго типізується і надає безліч переваг над колекціями, які зберігають свої елементи як Object. При спробі додати Customer до List<string> виникне помилка під час компіляції. Використання універсальних колекцій не викликає складнощів, оскільки не потрібно виконувати приведення типів під час виконання.
  • IEnumerable<(Of <(T>)>) є інтерфейсом, який дозволяє класам універсальних колекцій підтримувати перелічення за допомогою оператора foreach. Класи універсальних колекцій підтримують IEnumerable<(Of <(T>)>) так само, як не універсальні класи колекцій, наприклад ArrayList, підтримують IEnumerable.

Змінні IEnumerable в запитах LINQ

Змінні запитів LINQ визначені як IEnumerable<(Of <(T>)>) або як похідний тип, наприклад IQueryable<(Of <(T>)>). Якщо змінна запиту має тип IEnumerable<Customer>, це означає, що запит при виконанні виведе послідовність з нуля або більше об'єктів Customer:

IEnumerable<Customer> customerQuery = from cust in customers where cust.City == "Москва" select cust;

За бажанням звичайного синтаксису універсальних шаблонів можна уникнути за допомогою ключового слова var. Ключове слово var повідомляє компілятор про необхідність визначення типу змінної запиту за допомогою перегляду джерела даних, вказаного в слові from. У наступному прикладі створюється той самий скомпільований код, що і в попередньому прикладі:

 

var customerQuery2 = from cust in customers where cust.City == "Москва" select cust; foreach(var customer in customerQuery2){ Console.WriteLine(customer.LastName + ", " + customer.FirstName);}

Ключове слово var зручно, коли тип змінної є очевидним, або коли не потрібно явно вказувати вкладених універсальних типів, що наприклад, створюються запитами group. В цілому, якщо використовується var, важливо усвідомлювати, що код може бути складнішим для читання.

Приклад.

Визначимо як джерело даних клас:

class Customer

{

public string First { get; set; }

public string Last { get; set; }

public int ID { get; set; }

public string City { get; set; }

public string Zakaz;

}

Вибираємо замовників з Києва

//customers

List<Customer> customers = new List<Customer>()

{

new Customer {First="Александр"

Last="Андрусенко"

ID=100

City="Киев"

Zakaz = "цукерки"},

new Customer {First="Иван"

Last="Гринев"

ID=101

City="Киев"

Zakaz = "цукерки"}

};

 

var customerQuery2 =

from cust in customers

where cust.City == "Київ"

select cust;

 

foreach (var customer in customerQuery2)

{

Console.WriteLine(customer.Last + ", " + customer.First);

}

Console.ReadKey();

Основні операції запиту

Визначення джерела даних

В першу чергу в запиті LINQ потрібно вказати джерело даних. У C#, як і в більшості мов програмування, змінна має бути оголошена до її використання. У запиті LINQ першим йде слово from для вказівки джерела даних (customers) і змінна діапазону (cust):

 

//queryAllCustomers – це IEnumerable<Customer>var queryAllCustomers = from cust in customers select cust;

Змінна діапазону схожа із змінною ітерації в циклі foreach за винятком того, що у виразі запиту не відбувається фактичної ітерації. При виконанні запиту змінна діапазону використовуватиметься як посилання на кожен подальший елемент в customers. Оскільки компілятор може визначити тип cust, немає необхідності вказувати його в явному вигляді. Додаткові змінні діапазону можуть бути введені словом let.

Фільтрація

Можливо, найбільш поширеною операцією запиту є використання фільтру у вигляді логічного виразу. Результат створюється за допомогою ключового слова where. Фільтр фактично вказує елементи для виключення з вихідної послідовності. У наступному прикладі повертаються лише customers, що знаходяться в Москві:

 

var queryMoscowCustomers = from cust in customers where cust.City == "Москва" select cust;

 

Для використання потрібного числа виразів фільтру в where можна використовувати знайомі логічні оператори C# AND і OR. Наприклад, для отримання лише замовників з Москви і з ім'ям Іван слід написати наступний код:

 

where cust.City=="Москва" && cust.Name == "Іван"

 

Для отримання замовників з Москви або Смоленську слід написати наступний код:

where cust.City == "Москва" || cust.City == "Смоленськ"

Впорядкування

Часто доцільно відсортувати повернені дані. Пропозиція orderby сортує елементи послідовності залежно від компаратора за умовчанням для сортованого типа. Наприклад, наступний запит може бути розширений для сортування результатів на основі властивості Name. Оскільки Name є рядком, порівняння за умовчанням виконується в алфавітному порядку від А до Я:

 

var queryMoscowCustomers3 = from cust in customerswhere cust.City == "Москва" orderby cust.Name ascending select cust;

 

Для впорядкування результатів в зворотному порядку від Я до А використовується пропозиція orderby.descending.

Угрупування

Пропозиція group дозволяє групувати результати на основі вказаного ключа. Наприклад, можна вказати, що результати мають бути згруповані по City так, щоб всі замовники з Москви або Смоленську виявилися в окремих групах. В цьому випадку ключем є cust.City.

Примітка. Для демонстрації даного принципу в наступних прикладах використовуються явні типи. Також можна використовувати неявну типізацію для custQuery, group і customer, дозволяючи компілятору визначити точний тип:

 

// queryCustomersByCity – це IEnumerable<IGrouping<string, Customer>>var queryCustomersByCity =from cust in customersgroup cust by cust.City; // customerGroup – це IGrouping<string, Customer>foreach (var customerGroup in queryCustomersByCity){ Console.WriteLine(customerGroup.Key); foreach (Customer customer in customerGroup) { Console.WriteLine(" {0}", customer.Name); }}

Коли запит завершується пропозицією group, результати представляються у вигляді списку із списків. Кожен елемент в списку є об'єктом, що має член Кеу і список елементів, згрупованих по цьому ключу. При ітерації запиту, що створює послідовність груп, необхідно використовувати вкладений цикл foreach. Зовнішній цикл виконує ітерацію кожної групи, а внутрішній цикл – ітерацію членів кожної групи.

Якщо необхідно посилатися на результати операції угрупування, можна використовувати ключове слово into для створення ідентифікатора, який можна буде запитувати. Наступний запит повертає лише ті групи, які містять більше двох замовників:

 

// custQuery – це IEnumerable<IGrouping<string, Customer>>var custQuery =from cust in customersgroup cust by cust.City into custGroupwhere custGroup.Count() > 2 orderby custGroup.Key select custGroup;

З'єднання

Операції з'єднання створюють зв'язки між послідовностями, неявно змодельованими в джерелах даних. Наприклад, можна виконати з'єднання для пошуку всіх замовників в Москві, що замовили продукти у постачальників в Парижі. У LINQ пропозиція join завжди працює з колекціями об'єктів, а не безпосередньо з таблицями бази даних. У LINQ немає необхідності використовувати join так часто, як в SQL, оскільки зовнішні ключі в LINQ представлені в об'єктній моделі властивостями, що містять колекцію елементів. Наприклад, об'єкт Customer містить колекцію об'єктів Order. Замість виконання з'єднання, доступ до замовлень можна отримати за допомогою точкової нотації:

from order in Customer.Orders...

Вибір (Проектування)

Пропозиція select створює результати запиту і задає форму або тип кожного елементу, що повертається. Наприклад, можна вказати, чи будуть результати складатися з повних об'єктів Customer, лише з одного члена, підмножини членів або деяких абсолютно інших типів, на основі обчислень або створення нових об'єктів. Коли пропозиція select створює що-небудь відмінне від копії вихідного елементу, операція називається проекцією. Використання проекцій для перетворення даних є потужною можливістю виразів запитів LINQ.

Перетворення даних з LINQ

LINQ використовується не лише для відбіру даних. Це також потужний засіб для перетворення даних. За допомогою запиту LINQ можна використовувати вихідну послідовність як вхідні дані і змінювати її різними способами для створення нової вихідної послідовності. Можна змінити саму послідовність, не змінюючи елементів, за допомогою сортування і угрупування. Але, можливо, найбільш потужною функцією запитів LINQ є можливість створення нових типів. Це виконується в пропозиції select. Наприклад, можна виконати наступні завдання:

  • Об'єднати декілька вхідних послідовностей в одну вихідну послідовність, яка має новий тип.
  • Створити вихідні послідовності, елементи яких складаються лише з одного або декількох властивостей кожного елементу у вихідній послідовності.
  • Створити вихідні послідовності, елементи яких складаються з результатів операцій, що виконуються над вихідними даними.
  • Створити вихідні послідовності в іншому форматі. Наприклад, можна перетворити дані з рядків SQL або текстових файлів в XML.

Це лише декілька прикладів. Зрозуміло, ці перетворення можуть об'єднуватися різними способами в одному запиті. Більш того, вихідні послідовності одного запиту можуть використовуватися як вхідні послідовності для нового запиту.



Поделиться:


Последнее изменение этой страницы: 2017-02-21; просмотров: 217; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.145.191.214 (0.014 с.)