مقدمه
در درس قبل، با اجزای سازندهی زبان C# که تکنولوژی LINQ را ممکن میسازند،
آشنا شدیم. اکنون زمان آن است که این مفاهیم را به صورت عملی به کار بگیریم. از آنجایی که آرایهها
در C# اینترفیس IEnumerable<T> را پیادهسازی میکنند، آنها یکی از اولین و سادهترین
منابع دادهای هستند که میتوانیم با استفاده از LINQ روی آنها کوئری بزنیم. در این
درس، یاد میگیریم که چگونه با استفاده از هر دو سینتکس کوئری (Query Syntax) و سینتکس متد
(Method Syntax)، دادهها را از آرایهها فیلتر، مرتب و پرتاب (project) کنیم.
آمادهسازی مثال
برای شروع، بیایید دو آرایهی ساده به عنوان منبع دادهی خود تعریف کنیم. در طول این درس از این
آرایهها برای نمایش عملگرهای مختلف LINQ استفاده خواهیم کرد.
Program.cs
int[] numbers = { 5, 10, 8, 3, 6, 12, 9, 7 };
string[] names = { "Ali", "Sara", "Reza", "Mina", "Babak" };
فیلتر کردن دادهها با where
یکی از رایجترین کارها در کوئری زدن، فیلتر کردن است؛ یعنی انتخاب عناصری که یک شرط خاص را برآورده
میکنند. در LINQ، این کار با استفاده از عملگر where انجام میشود.
سینتکس کوئری (Query Syntax)
این سینتکس شبیه به SQL است و برای بسیاری از افراد، خوانایی بالاتری دارد.
Program.cs
var queryResult = from n in numbers
where n > 7
select n;
Console.WriteLine("Numbers greater than 7:");
foreach (var number in queryResult)
{
Console.Write($"{number} ");
}
سینتکس متد (Method Syntax)
در این سینتکس، ما از متد بسطی Where به همراه یک عبارت لامبدا برای تعریف شرط فیلتر استفاده
میکنیم.
Program.cs
var methodResult = names.Where(name => name.Contains("a"));
Console.WriteLine("\nNames containing 'a':");
foreach (var name in methodResult)
{
Console.Write($"{name} ");
}
نکته مهم: هر دو سینتکس در نهایت توسط کامپایلر به یک کد مشابه تبدیل میشوند و از
نظر عملکردی تفاوتی ندارند. انتخاب بین آنها بیشتر به سلیقه و خوانایی در سناریوی مورد نظر بستگی
دارد.
مرتبسازی دادهها با orderby
برای مرتب کردن نتایج کوئری، از عملگر orderby (در سینتکس کوئری) یا متدهای OrderBy و
OrderByDescending (در سینتکس متد) استفاده میکنیم.
Program.cs
var sortedNumbersQuery = from n in numbers
orderby n descending
select n;
Console.WriteLine("\nNumbers sorted descending:");
Console.WriteLine(string.Join(", ", sortedNumbersQuery));
var sortedNamesMethod = names.OrderBy(name => name);
Console.WriteLine("\nNames sorted alphabetically:");
Console.WriteLine(string.Join(", ", sortedNamesMethod));
پرتاب کردن دادهها با select
اغلب اوقات، ما نمیخواهیم خود عناصر اصلی را برگردانیم، بلکه میخواهیم آنها را به یک شکل جدید
پرتاب (Project) کنیم. برای مثال، ممکن است بخواهیم از یک آرایهی عددی، مربع هر
عدد را برگردانیم، یا از یک آرایهی رشتهای، طول هر رشته را. این کار با عملگر select انجام
میشود.
Program.cs
var projectedNumbers = from n in numbers
select new { Original = n, Square = n * n };
Console.WriteLine("\nProjected numbers:");
foreach (var item in projectedNumbers)
{
Console.WriteLine(item);
}
خروجی این کد، لیستی از اشیاء ناشناس خواهد بود:
Projected numbers:
{ Original = 5, Square = 25 }
{ Original = 10, Square = 100 }
...
اجرای تأخیری (Deferred Execution)
یکی از مهمترین مفاهیم در LINQ، اجرای تأخیری است. وقتی شما یک کوئری LINQ
را تعریف میکنید (مانند var queryResult = ... آن کوئری در همان لحظه اجرا
نمیشود. در واقع، شما فقط "دستورالعمل" یا "نقشهی" کوئری را ساختهاید. کوئری
تنها زمانی واقعاً اجرا میشود که شما شروع به پیمایش نتایج آن کنید، معمولاً با یک حلقهی
foreach یا با فراخوانی متدهایی مانند ToList()، ToArray()، First() یا Count(). این
ویژگی به LINQ اجازه میدهد تا کوئریها را بهینه کرده و چندین عملیات را در یک مرحلهی
واحد ترکیب کند.