اپراتورهای Conversion در LINQ

28 اردیبهشت 1398
درسنامه درس 9 از سری آموزش LINQ
LINQ-conversion

با سلام با یکی دیگر از آموزش های LINQ در C# در خدمت شما هستیم در این بخش قصد داریم Conversion operators را بررسی کنیم.

conversion operators چیست؟

همان طور که از نام آن مشخص است از این اپراتور ها برای تبدیل انواع لیست و مجموعه به سایر اشیا استفاده می شود.

انواع اپراتور های conversion عبارت اند از:

  • TOLIST
  • TOARRAY
  • TOLOOKUP
  • CAST
  • ASENUMERABLE
  • ToDictionary

در جدول زیر خلاصه ای از کاربرد هر یک از اپراتور های conversion آورده شده است:

کاربرد نام اپراتور
این اپراتور یک مجموعه ای از داده ها را به لیست تبدیل می کند. ToList
این اپراتور یک مجموعه ای از داده ها را به آرایه تبدیل می کند. ToArray
توسط این اپراتور می توان محتویات یک مجموعه داده را به صورت Key و Element استخراج کرد. ToLookup
این اپراتور به نوعی عملیات Cast را انجام می دهد. Cast
از این اپراتور برای تبدیل داده ها به نوع Enumerable استفاده می شود. AsEnumerable
توسط این اپراتور می توان اطلاعات یک منبع داده را به صورت Key و Value استخراج کرد. ToDictionary

متد ToList

کاربرد این متد در تبدیل داده های یک منبع به نوع داده ی لیست است که الگوی استفاده از آن به صورت زیر است:

List<string> result = obj.ToList();

در بین <> باید نوع داده ی اولیه که قرار است به لیست تبدیل شود قرار بگیرد. مثلا در این الگو فرض شده نوع داده obj از نوع string است.

به مثال زیر توجه کنید:

using System;
using System.Linq;
using System.Collections.Generic;
namespace LINQExamples

{
    class Program
    {
        static void Main(string[] args)
        {
            string[] countries = { "US", "UK", "India", "Russia", "China", "Australia", "Iran" };
            List<string> result = countries.ToList();
            foreach (string s in result)
            {
                Console.WriteLine(s);
            }
            Console.WriteLine("Type of countries: " + countries.GetType());
            Console.WriteLine("Type of result: "+result.GetType());
            Console.ReadLine();
        }
    }
}

در این مثال ساده یک آرایه از جنس string تعریف شده که در ادامه با استفاده از متد ToList قصد داریم آن را به لیست تبدیل کنیم بدیهی است که نوع داده ی result لیستی با داده هایی از جنس string خواهد بود.

به منظور اطمینان از انجام تبدیل با استفاده از متد GetType نوع اشیای countries و result را در آخر چاپ نموده ایم که خروجی آن به صورت زیر است:

خروجی مثال ToList
خروجی مثال ToList

پیاده سازی کد به روش Query به صورت زیر است:

List<string> result = (from x in countries
select x).ToList();

توجه: کاربرد اصلی این متد در مبحث LINQ to SQL و Entity Framework است، به همین منظور بررسی دقیق تر آن را به بعد موکول می کنیم.

متد ToArray

این متد نیز اطلاعات گرفته شده از منبع داده را به آرایه تبدیل می کند که الگوی استفاده از آن به صورت زیر است:

string[] arrayname= obj.ToArray();

به نوع  string[] توجه کنید که به نوع obj بستگی دارد. مثلا در این الگو فرض شده نوع داده ی obj یک لیست با نوع داده ی string است.

به مثال زیر توجه کنید:

using System;
using System.Linq;
using System.Collections.Generic;
namespace LINQExamples

{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> num = new List<int> {1,2,3,4,5,6,7,8,9 };
            int[] arraynum = num.ToArray();
            foreach (int s in arraynum)
            {
                Console.WriteLine(s);
            }            
            Console.WriteLine("Type of num: " + num.GetType());
            Console.WriteLine("Type of arraynum: " + arraynum.GetType());
            Console.ReadLine();
        }
    }
}

در این مثال یک لیست با نوع داده ی int تعریف شده که با استفاده از متد ToArray آن را به آرایه ای از نوع int تبدیل کرده ایم. مانند مثال قبلی در این مثال نیز نوع هر دو شئ را در پایان چاپ کرده ایم.

روش Query:

 int[] arraynum = (from m in num
select m).ToArray();
خروجی مثال ToArray
خروجی مثال ToArray

توجه: کاربرد اصلی این متد در مبحث LINQ to SQL و Entity Eramework است، به همین منظور بررسی دقیق تر آن را به بعد موکول می کنیم.

متد ToLookup

با استفاده از این متد می توان به نوعی مقادیر یک منبع داده را به صورت Key و Element استخراج کرد. توضیح کاربرد این متد را در قالب مثال بررسی می کنیم.

به مثال زیر توجه کنید:

using System;
using System.Linq;
using System.Collections.Generic;
namespace LINQExamples

{
    class Program
    {
        static void Main(string[] args)
        {
            List<Employee> objEmployee = new List<Employee>()
             {
            new Employee(){ Name="Ashish Sharma", Department="Marketing", Country="India"},
            new Employee(){ Name="John Smith", Department="IT", Country="Australia"},
            new Employee(){ Name="Kim Jong", Department="Sales", Country="China"},
            new Employee(){ Name="Marcia Adams", Department="HR", Country="USA"},
            new Employee(){ Name="John Doe", Department="Operations", Country="Canada"}
            };
            var emp = objEmployee.ToLookup(x => x.Department);
            Console.WriteLine("Grouping Employees by Department");
            Console.WriteLine("---------------------------------");
            foreach (var KeyValurPair in emp)
            {
                Console.WriteLine(KeyValurPair.Key);
                // Lookup employees by Department
                foreach (var item in emp[KeyValurPair.Key])
                {
                   Console.WriteLine("\t" + item.Name + "\t" + item.Country);
               }
            }
            Console.ReadLine();
        }
    }
    class Employee
    {
        public string Name { get; set; }
        public string Department { get; set; }
        public string Country { get; set; }
    }
}

یک لیست با نوع  داده ی کلاس Employee در اختیار داریم که با اعضایی مشخص پر شده است. توجه داشته باشید این کلاس دارای سه فید Name و Department و Country است، در این مثال قصد داریم هر شخص را بر اساس فیلد Department دسته بندی کنیم. حالا مراحل زیر را قدم به قدم انجام دهید:

کد بالا را بدون تغییر در IDE خود بنویسید و نشانگر موس را بر روی کلمه ی var قرار دهید و به مقدار TKey و TElement دقت کنید، نوع TKey که در این مثال از نوع string است که در واقع همان نوع داده ی فیلد Department است که به صورت (ToLookup(x => x.Department نوشته شده است. به نوع داده ی TElement دقت کنید که از نوع کلاس Employee است.

حالا نوبت به دسترسی به مقادیر Key و Element است. foreach اول را در نظر بگیرید که نام شئ پیماشگر آن KeyValurPair (دلخواه) انتخاب شده و به محض نوشتن آن اولین کلمه ای که برای آن پیشنهاد می شود Key است، بنابراین با استفاده از کلمه ی Key دقیقا به مقدار Key آن دسترسی پیدا می کنیم. حالا به foreach دوم توجه کنید و موس را بر روی پیمایشگر حلقه نگه دارید تا مشاهده کنید که نوع آن در واقع کلاس Employee است، پس برای دسترسی به مقدار Element به صورت [emp[KeyValurPair.Key عمل می کنیم. در خط بعد نیز با استفاده از item که به نوعی شئ از کلاس Employee است به تمامی فیلد های آن دسترسی داریم برنامه را اجرا و خروجی را مشاهده کنید.

روش Query:

 var emp = from y in objEmployee.ToLookup(x =>x.Department)
select y;
خروجی مثال اول ToLookup
خروجی مثال اول ToLookup

برای آشنایی بیشتر با این متد به مثال دوم توجه کنید:

using System;
using System.Linq;
using System.Collections.Generic;
namespace LINQExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> NumList = new List<string>() { "One","Two", "Three", "Four","Five", "Six", "seven" };
            ILookup<int,string> Num = NumList.ToLookup(x =>x.Length);
            foreach (var item in Num)
            {
                Console.WriteLine("Length: "+item.Key);
                foreach (var item2 in Num[item.Key])
                {
                    Console.WriteLine("\t"+"The number: "+item2);
                }
            }
            Console.ReadKey();
        }
    }
}

هدف ما در این مثال ساده، دسته بندی کلمات موجود در لیست بر اساس طول رشته است.

به قسمت <ILookup<int,string توجه کنید در این مثال تصمیم گرفتیم که به جای کلمه ی var از نوع داده اصلی استفاده کنیم. توجه داشته باشید در این مثال جنس داده ی Key از نوع int (طول رشته) و جنس داده ی Element از نوع string (اعضای لیست) است. به طور کلی عملیاتی که در داخل متد ToLookup انجام می پذیرد باعث دستیابی ما به Key می شود.

در این مثال بخصوص، مقدار Key برابر با طول رشته است و مقدار Element برابر با کلمات موجود در آرایه است. برای دستیابی به مقادیر key و Element در حلقه های موجود مانند مثال قبل عمل می کنیم. برنامه را اجرا و خروجی را مشاهده کنید.

روش Query:

ILookup<int, string> Num = (from z in NumList
select z).ToLookup(x => x.Length);
خروجی مثال دوم ToLookup
خروجی مثال دوم ToLookup

متد Cast

کاربرد این متد برای تبدیل نوع داده ها استفاده می شود که عملیات تبدیل باید بر اساس قوانین خاصی صورت بگیرد وگرنه باعث پرتاب خطا خواهد شد.

الگوی استفاده از آن به صورت زیر است:

IEnumerable<string> result = obj.Cast<string>();

داده result همیشه از نوع IEnumerable خواهد بود و فقط لازم است نوع داده ی مقصد در متد Cast و IEnumerable در داخل <> نوشته شود. لازم به ذکر است که متد Cast هیچگونه پارامتر ورودی ندارد و فقط به صورت Generic استفاده می شود.

به مثال زیر توجه کنید:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections;

namespace LINQExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Object> obj = new List<Object>();
            obj.Add(2.25);
            obj.Add(4.3);
            obj.Add(7.3);
            obj.Add(13.75);
            IEnumerable<double> result = obj.Cast<double>();
            foreach (var item in result)
            {
                Console.WriteLine(item);
            }
            Console.WriteLine(obj.GetType());
            Console.WriteLine(result.GetType());
            Console.ReadLine();
        }
    }
}
    

نوع اطلاعات موجود در List همگی از نوع Object هستند. هدف ما در این مثال تبدیل Object به double است که این کار توسط متد Cast انجام خواهد شد.

روش Query:

IEnumerable<double> result = from x in obj.Cast<double>()
select x;
خروجی مثال Cast
خروجی مثال Cast

متد AsEnumerable

از این متد برای تبدیل داده ها به Enumerable استفاده می شود که الگوی استفاده از آن به صورت زیر است:

var result = Objname.AsEnumerable();

متد AsEnumerable پارامتر ورودی ندارد و کاربرد آن بسیار ساده است. به مثال زیر توجه کنید:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
namespace LINQExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] array = new string[] {"Name","Lastname","Email","Password" };
            IEnumerable result = array.AsEnumerable();
            foreach (var number in result)
            {
                Console.WriteLine(number);
            }
            Console.ReadLine();
        }
    }
}

در این مثال یک آرایه string در اختیار داریم که با استفاده از متد AsEnumerable آن را به نوع IEnumerable تبدیل کرده ایم. خروجی این کد همان اعضای آرایه است فقط نوع دستیابی به آن ها متفاوت است.

متد ToDictionary

اگر با کلاس Dictionary در C# آشنایی داشته باشید می دانید که این کلاس توانایی ایجاد Key های یکتا برای مقادیر مختلف را دارد. کاربرد متد ToDictionary دقیقا به همین منظور است. اجازه دهید توضیحات این متد مهم را بر روی یک مثال بررسی کنیم.

مثال:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
namespace LINQExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            
            List<Student> objStudent = new List<Student>()
            {
                new Student() { Id=1,Name = "Suresh Dasari", Gender = "Male",Location="Chennai" },
                new Student() { Id=2,Name = "Rohini Alavala", Gender = "Female", Location="Chennai" },
                new Student() { Id=3,Name = "Praveen Alavala", Gender = "Male",Location="Bangalore" },
                new Student() { Id=4,Name = "Sateesh Alavala", Gender = "Male", Location ="Vizag"},
                new Student() { Id=5,Name = "Madhav Sai", Gender = "Male", Location="Nagpur"}
            };
            Dictionary<int,string> result= objStudent.ToDictionary(x => x.Id, x => x.Name);
            foreach (var stud in student)
            {
                Console.WriteLine(stud.Key + "\t" + stud.Value);
            }

            Console.ReadLine();
        }
    }
    class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
        public string Location { get; set; }

    }
}

در ابتدا یک لیست با نوع داده ی کلاس Student در اختیار داریم که با مقادیر مناسب و با توجه به Property های کلاس Student آن را پر کرده ایم. هدف اصلی ما در این مثال قرار دادن فیلد ID به عنوان Key و فیلد Name به عنوان Value است.

توجه داشته باشید نوع دو فیلد مذکور به ترتیب int و string است به همین خاطر نوع داده ی result به صورت <Dictionary<int,string تعریف شده است. اگر نشانگر موس را بر روی Dictionary نگه دارید، خواهید دید که مقدار اول قرار گرفته شده در <,> حکم Key را دارد و مقدار دوم Value است.

در مرحله ی بعد توسط شئ objStudent متد ToDictionary را فراخوانی می کنیم. در این مثال قصد داشتیم ID را به عنوان Key انتخاب کنیم به همین دلیل در جایگاه پارامتر اول قرار می گیرد و بعد از آن مقدار Value باید قرار بگیرد. برای چاپ مقادیر کافی است با استفاده از یک حلقه به مقادیر Key و Value دست پیدا کنیم و آن ها را در خروجی چاپ کنیم. کد را اجرا و خروجی آن را مشاهده کنید.

روش Query:

 Dictionary<int, string> result = (from x in objStudent
select x).ToDictionary(x => x.Id, x => x.Name);
خروجی مثال ToDictionary
خروجی مثال ToDictionary

حالا سعی کنید در کد بالا تغییرات زیر را انجام دهید:

Dictionary<string, string> result = (from x in objStudent
select x).ToDictionary(x => x.Location, x => x.Name);

برنامه را اجرا و خطای آن را بررسی کنید. همان طور که می دانید مقدار Key حتما باید یکتا باشد. در این مورد فیلد Location به عنوان Key در نظر گرفته شد در حالی که مقادیر آن دارای تکرار است به همین دلیل اجرای برنامه با خطا همراه می شود اما در مورد Value این قضیه صحت ندارد و با وجود مقادیر تکراری برنامه بدون خطا اجرا خواهد شد.

این بخش از آموزش هم به پایان رسید توجه داشته باشید دو متد ToDictionary و ToLookup بسیار کاربردی و مهم هستند پس لازم است با استفاده از آن ها مثال های بیشتری حل کنید چون در مبحث LINQ to SQL بسیار کاربردی خواهد بود. تعداد کمی از متد های پایه در مبحث LINQ باقی مانده است که در جلسه بعدی مهم ترین و کاربردی ترین آن ها را بررسی خواهیم کرد.

موفق باشید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش LINQ توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.