با سلام خدمت کاربران عزیز در این جلسه قصد داریم چند اپراتور باقی مانده در مبحث LINQ را بررسی کنیم تا پیش نیاز لازم را برای شروع مبحث LINQ to SQL داشته باشیم و از جلسه ی بعدی به توضیح و بررسی آن بپردازیم.
متد Aggregate
کاربرد این متد زمانی است که می خواهیم کل عناصر یک مجموعه بر اساس الگوی خاصی رفتار کنند، این رفتار با شروع از عنصر اول و دوم و اعمال نتیجه به عنصر سوم و الی آخر انجام می شود. احتمالا توضیح آن کمی گیج کننده بود اجازه دهید با بررسی یک مثال کاربرد آن را شرح دهیم.
مثال:
using System; using System.Linq; namespace LINQExamples { class Program { static void Main(string[] args) { int[] Num = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; Console.WriteLine("Find the Product of the elements:"); double Average = Num.Aggregate((a, b) => a * b); Console.WriteLine("The Product is {0}", Average); string[] charlist = { "a", "b", "c", "d" }; var concta = charlist.Aggregate((a, b) => a + ',' + b); Console.WriteLine("Concatenated String: {0}", concta); Console.ReadLine(); } } }
در ابتدای برنامه یک آرایه int
در اختیار داریم که اعضای آن اعداد 1 تا 9 هستند. هدف ما گرفتن فاکتوریل از اعضای آرایه است.
این الگو به راحتی در متد Aggregate
قابل پیاده سازی است برای این منظور کد a, b) => a * b)
درون متد می نویسیم. منظور از a عدد اول و b عدد دوم است. در مرحله ی اول a=1
و b=2
است که حاصل ضرب آن ها عدد 2 خواهد بود حالا a=2
(حاصل مرحله ی اول) و b=3 است که حاصل ضرب آن ها 6 خواهد بود به همین ترتیب در مرحله ی بعد a=6
و b=4
می شود تا به پایان برسد.
در مرحله ی بعد یک آرایه ی string
تعریف شده است که ما قصد داریم اعضای آن همراه با ','
یا هر چیز دیگری از هم جدا کنیم برای تکرار این الگو برای تمامی اعضا کدa, b) => a + "," + b)
را در متد می نویسیم.
برای پیاده سازی کد به روش Query باید تغییرات زیر را انجام دهید:
double Average = (from x in Num select x).Aggregate((a, b) => a * b); string concta = (from x in charlist select x).Aggregate((a, b) => a + "," + b);

همان طور که در خروجی مشخص است مقدار 9! محاسبه شده است و اعضای آرایه ی string
با ','
جدا شده اند.
حالا تغییرات زیر را در کد بالا اعمال کنید و خروجی را مشاهده کنید:
double Average = Num.Aggregate((a,b)=>(a+1)+b); string concta = charlist.Aggregate((a, b) => a + "->\t" + b);
در مرحله ی اول a=1
و b=2
خواهد بود. همان طور که در الگو مشخص شده ابتدا باید یک واحد به a اضافه و سپس با b جمع شود که حاصل برابر 4 خواهد شد در مرحله ی بعد a=4
و b=3
می شود. دوباره باید به مقدار a یک واحد اضافه و سپس با b جمع شود تا حاصل برابر 8 شود این عملیات تا رسیدن به آخرین عضو آرایه به همین ترتیب ادامه خواهد داشت تا در آخر عدد 53 حاصل شود.
در مورد آرایه ی string
هدف ما ابتدا چاپ ->
و سپس ایجاد کارکتر کنترلی "t\"
است. برنامه را اجرا و خروجی را مشاده کنید.

متد GroupBy
از این متد برای گروه بندی آیتم ها در یک مجموعه یا لیست بر اساس یک کلید خاص و یک فیلد استفاده می شود. این متد از نظر کاربرد تا حد زیادی به GroupBy
در SQL شباهت دارد.
به مثال زیر توجه کنید:
using System; using System.Collections.Generic; using System.Linq; namespace Linqtutorials { class Program { static void Main(string[] args) { List<Student> objStudent = new List<Student>() { new Student() { Name = "Suresh Dasari", Gender = "Male",Location="Chennai" }, new Student() { Name = "Rohini Alavala", Gender = "Female", Location="Chennai" }, new Student() { Name = "Praveen Alavala", Gender = "Male",Location="Bangalore" }, new Student() { Name = "Sateesh Alavala", Gender = "Male", Location ="Vizag"}, new Student() { Name = "Madhav Sai", Gender = "Male", Location="Nagpur"} }; var student = objStudent.GroupBy(x => x.Location); foreach (var sitem in student) { Console.WriteLine(sitem.Key+" "+ sitem.Count()); Console.WriteLine(); foreach (var stud in sitem) { Console.WriteLine(stud.Name + "\t" + stud.Location); } Console.WriteLine(); } Console.ReadLine(); } } class Student { public string Name { get; set; } public string Gender { get; set; } public string Location { get; set; } } }
هدف ما در این مثال مرتب سازی اعضای یک مجموعه بر اساس فیلد Location
است. توجه داشته باشید که در این متد منظور از Key همان فیلدی است که اطلاعات بر اساس آن طبقه بندی می شود که در این مثال مقدار Key فیلد Location
است.
در foreach
اول هدف ما چاپ مقادیر فیلد Location
و تعداد آن است همان طور که مشاهده می کنید برای دستیابی به مقادیر فیلد از کلمه ی Key استفاده شده است.
در foreach
دومی که در داخل اولی قرار دارد، قصد داریم به فیلد های کلاس Student
دست پیدا کنیم به همین منظور بر روی شئ پیمایش کننده حلقه ی اول یک پیمایش دیگر انجام می دهیم اگر موس را بر روی stud
قرار دهید می بینید که شئ از کلاس Student
است. بنابراین به تمامی فیلد های آن دسترسی دارد و می توان با دستور مناسب آن را چاپ نمود.
روش Query:
var student = from x in objStudent.GroupBy(x => x.Location) select x;
یا
var student = from x in objStudent group x by x.Location;

احتمالا متوجه شدید که این متد شباهت بسیار زیادی به متد ToLookup
دارد حالا اجازه دهید همین مثال را با متد ToLookup
تغییر دهیم و آن را بررسی کنیم.
تغییرات زیر را بر روی مثال قبلی انجام دهید:
var student = objStudent.ToLookup(x => x.Location); foreach (var sitem in student) { Console.WriteLine(sitem.Key+" "+ sitem.Count()); Console.WriteLine(); foreach (var stud in student[sitem.Key]) { Console.WriteLine(stud.Name + "\t" + stud.Location); } Console.WriteLine(); }
فقط کافی است جای GroupBy
را با ToLookup
عوض کنید در ضمن در کد بالا در حلقه ی دوم می توانید به جای [student[sitem.Key
از sitem
(پیمایشگر حلقه ی اول) استفاده کنید.
اگر کد را اجرا کنید می بینید که خروجی دقیقا مانند قبل است فقط روش پیاده سازی آن متفاوت است.
متد SequenceEqual
یک متد مقایسه گر است که تست تساوی را بر روی دو دنباله از اطلاعات انجام می دهد. خروجی این متد در صورتی که تمامی عناصر یک مجموعه دو به دو یکسان باشند true و در غیر این صورت false است.
به مثال زیر توجه کنید:
using System; using System.Collections.Generic; using System.Linq; namespace Linqtutorials { class Program { static void Main(string[] args) { string[] arr1 = { "welcome", "to", "tutlane", "com" }; string[] arr2 = { "welcome", "TO", "TUTLANE", "com" }; string[] arr3 = { "welcome", "to", "tutlane" }; string[] arr4 = { "WELCOME", "TO", "TUTLANE" }; bool res1 = arr1.SequenceEqual(arr2); bool res2 = arr1.SequenceEqual(arr2, StringComparer.OrdinalIgnoreCase); bool res3 = arr1.SequenceEqual(arr3); bool res4 = arr3.SequenceEqual(arr4, StringComparer.OrdinalIgnoreCase); Console.WriteLine("Result1: {0}", res1); Console.WriteLine("Result2: {0}", res2); Console.WriteLine("Result3: {0}", res3); Console.WriteLine("Result4: {0}", res4); Console.ReadLine(); } } }
اعضای موجود در آرایه های arr1
و arr2
کاملا یکسان هستند اما در کوچک و بزرگ بودن حروف متفاوت اند. در دو آرایه ی arr3
و arr4
هم شرایط به همین صورت است. با استفاده از متد SequenceEqual
شرایط تساوی را بررسی کردیم. برنامه را اجرا و خروجی را مشاهده کنید می بینید که Result1
و Result3
هر دو false هستند.
Result1
حاصل تست تساوی بین دو آرایه ی arr1
و arr2
است. پس نتیجه می گیریم که متد SequenceEqual
به بزرگ یا کوچک بودن حروف حساس است برای این که این حساسیت را از بین ببریم باید از StringComparer.OrdinalIgnoreCase
در متد استفاده کنیم. می بینید که Result2 و Result4 هر دو true هستد چون در بررسی تساوی از StringComparer.OrdinalIgnoreCase
در متدSequenceEqual
استفاده کرده ایم.
IComparable
برای آن کلاس و نوشتن متد CompareTo
است.متد Concat
همان طور که از نام این متد ساده پیداست کاربرد آن در وصل کردن دو مجموعه به یکدیگر است به طوری که اگر در دو مجموعه عنصری تکراری وجود داشته باشد آن عنصر حذف نخواهد شد و در مجموعه ی جدیدی که حاصل اتصال دو مجموعه قبلی است عنصر تکراری به دفعات تکرار در دو مجموعه قبلی تکرار خواهد شد.
این متد تا حدودی شبیه به Union
است با این تفاوت که متد Union عناصر تکراری را حذف می کرد و در مجموعه ی جدید عنصری که دارای تکرار بود فقط یک بار در نظر گرفته می شد. برای درک بیشتر به شکل زیر که مفهوم کلی متد Concat
را نشان می دهد توجه کنید:

مثال :
using System; using System.Collections.Generic; using System.Linq; namespace Linqtutorials { class Program { static void Main(string[] args) { string[] arr1 = { "a", "b", "c","b", "d" }; string[] arr2 = { "c", "d", "e", "f","a" }; IEnumerable<string> result = arr1.Concat(arr2); string res = result.Aggregate((a,b)=>a+","+b); foreach (var item in res) { Console.Write(item); } Console.ReadLine(); } } }
در این مثال دو آرایه ی arr1
و arr2
که هر دو دارای عناصر تکراری هستند و با استفاده از متد Concat
به هم متصل شده اند. مشاهده می کنید که هیچ حذفی صورت نگرفته و تمامی عناصر تکراری در خروجی چاپ شده اند.
روش Quey:
IEnumerable<string> result = (from x in arr1 select x).Concat(arr2);

متد Range
از این متد برای تولید دنباله ای از اعداد در یک محدوده ی خاص استفاده می شود.
الگوی استفاده از آن به صورت زیر است:
IEnumerable<int> obj = Enumerable.Range(int start, int count);
این متد بر روی هیچ مجموعه یا شئ فراخوانی نمی شود و به صورت static استفاده می شود و در کلاس Enumerable
قرار دارد. هر دو پارامتر ورودی آن از نوع int
هستند که اولی مشخص می کند، تولید دنباله از چه عددی شروع شود و پارامتر دوم تعداد اعضای دنباله را مشخص می کند.
به مثال زیر توجه کنید:
using System; using System.Collections.Generic; using System.Linq; namespace Linqtutorials { class Program { static void Main(string[] args) { IEnumerable<int> obj = Enumerable.Range(100, 50); foreach (var item in obj) { Console.WriteLine(item); } Console.ReadLine(); } } }
در این مثال شروع شمارش از 100 و تعداد آن ها 10 در نظر گرفته شده بنابراین خروجی از 100 تا 109 خواهد بود که توسط foreach
قابل دستیابی است.
متد Repeat
این متد یک عدد را به تعداد مرتبه ی مشخصی تکرار می کند که الگوی استفاده از آن به صورت زیر است:
IEnumerable<int> obj = Enumerable.Repeat(int element, int count);
این متد بر روی هیچ مجموعه یا شئ فراخوانی نمی شود و به صورت static استفاده می شود و در کلاس Enumerable
قرار دارد. هر دو پارامتر ورودی آن از نوع int
هستند که اولی مشخص می کند، چه عددی باید تکرار شود و پارامتر دوم تعداد تکرار را مشخص می کند.
به مثال زیر توجه کنید:
using System; using System.Collections.Generic; using System.Linq; namespace Linqtutorials { class Program { static void Main(string[] args) { IEnumerable<int> obj = Enumerable.Repeat(524, 3); foreach (var item in obj) { Console.WriteLine(item); } Console.ReadLine(); } } }
در این مثال عدد 524 که پارامتر اول متد Repeat
است 3 با تکرار می شود.
خب دوستان مقدمه ی آموزش LINQ در C# در این بخش به پایان می رسد. در طول دوره ی مقدماتی سعی شد متدهایی که کاربرد بیشتری دارند با مثال های بیشتری بررسی شوند. متدهایی مثل AsEnumerable
و Cast
و Range
و چند متد دیکر که کمتر در مورد آن ها بحث شد متدهایی هستند که به تنهایی هیچ کاربردی ندارند و استفاده از آن ها بی معنی است و زمانی کاربرد آن ها مفید است که در کنار دیگر متدها استفاده شود.
در قسمت های بعدی آموزش سعی می شود در مثال های پیچیده تر از این متدها استفاده کنیم تا کاربرد دقیق آن ها درک کنید. کلیه ی مثال های بررسی شده در طی این دوره شامل مبحث LINQ to Object بودند بنابراین از قسمت بعدی آموزش مبحث LINQ to SQL را شروع می کنیم.
موفق باشید.