استفاده از روش متدی

LINQ مجموعه ای از متدهای توسعه یافته هست که به رابط IEnumerable<T> الحاق شده اند. این متد ها در فضای نامی System.Linq وجود دارند و عضوی از کلاس استاتیک Enumerable هستند. قبلا یاد گرفته اید که متدهای توسعه یافته نوع خاصی از متد ها هستند که برای توسعه کلاس هایی که به سورس آنها دسترسی ندارید به وجود آمده اند.به عنوان مثال شما می توانید متدی به نام ToTitleCase() را به کلاس System.String الحاق کنید که با صدا زدن آن به وسیله یک رشته ، حروف اول کلمات تشکیل دهنده آن(رشته) به حالت بزرگ نمایش داده شوند. اجازه دهید در مورد متد Select<TSource,TResult>() از فضای نامی System.Linq توضیح دهیم.همانطور که در زیر می بینید این متد به رابط IEnumerable<T> الحاق شده است.

public static IEnumerable<TResult> Select<TSource, TResult>(
    this IEnumerable<TSource> source, Func<TSource, TResult> selector)

اولین پارامتر از یک متد توسعه یافته مشخص کننده نوعی است که توسعه می دهد. با کلمه کلیدی this شروع و بعد از آن به ترتیب نوع و نام نمونه متغیر قرار می گیرد. همانطور که می بینید نوع خروجی متد بالا IEnumerable<T> است.این به شما اجازه می دهد که متد ها را به صورت زنجیره ای فراخوانی کنید. همانطور که در درس های قبلی گفته شد برای فراخوانی متدهای LINQ شما باید از عبارات لامبدا استفاده کنید. گرچه شما می توانید به جای عبارات لامبدا از متد های بی نام هم استفاده کنید ولی استفاده از عبارات لامبدا کوتاه تر ، ساده تر است و کد شما را خوانا تر می کند. در این درس فرض شده است که خواننده اطلاعات خوبی از عبارات لامبدا دارد. در ادامه شما با روش جدیدی برای پرس و جو از منبع داده آشنا می شوید و آن استفاده از شکل متدی LINQ است . در این روش شما فقط باید متد مورد نظر خود را صدا زده و اطلاعات مورد نظر خود را صرف نظر از الگوریتم آن بدست آورید. .Net Framework شامل نماینده هایی(delegate) است که می توانند متدهایی با تعداد پارامتر های مختلف و نوع خروجی متفاوت در خود نگه دارند. اگر به تعریف متد Select دقت کنید می بینید که پارامتر دوم از این متد شامل نماینده ی عمومی با نوع Func<TSource,TResult> است. نماینده می تواند متدهایی که پارامتر اول آنها از نوع TSource و نوع خروجی آنها TResult است را قبول کند. به عنوان مثال ، Func<string,int> می تواند متدی که یک پارامتر از نوع string و خروجی از نوع int دارد را بپذیرد. در زیر لیست نماینده هایی را مشاهده می کنید که می توانید بسته به تعداد پارامتر های متد خود از آنها استفاده کنید.

نماینده توضیح
Func<T1, TResult> متدی با یک پارامتر و یک خروجی را در خود ذخیره می کند.
Func<T1, T2, TResult> متدی با 2 پارامتر و یک خروجی در خود ذخیره می کند.
Func<T1,T2,T3,TResult> متدی با 3 پارامتر ورودی و یک خروجی در خود ذخیره می کند.
Func<T1,T2,T3,T4, TResult> متدی با 4 پارامتر ورودی و یک خروجی در خود ذخیره می کند

با توجه به الگوی موجود در جدول بالا می توانید شکل نماینده برای متدهای با تعداد پارامتر بیشتر را حدس بزنید. این الگو را می توان تا سقف 16 پارامترادامه داد. اگر دوباره به شکل کلی متد Select() نگاهی بیندازید می بینید که دومین پارامتر آن ارجاع به متدی دارد که دارای یک پارامتر و یک مقدار برگشتی است. اجازه دهید مثالی را بررسی کنیم که نحوه ی استفاده از متد Select() با عبارات لامبدا را مشخص می کند.

int[] numbers = { 1, 2, 3, 4, 5 };

var result = numbers.Select(n => n);

foreach(var n in result)
{
    Console.Write(n + " ");
}
1 2 3 4 5

این نکته را یادآور می شویم که اولین پارامتر یک متد الحاقی در واقع یک پارامتر نیست بلکه مشخص کننده این است که قصد توسعه کدام نوع را داریم. در نتیجه دومین پارامتر که یک عبارت لامبدا را می پذیرد تنها پارامتری است که باید در متد Select() مشخص کنید. در متد Select() ، از عبارت لامبدایی استفاده شده است که یک پارامتر صحیح را دریافت می کند و خروجی از نوع صحیح را بر میگرداند. اگر شما با عبارات لامبدا آشنایی نداشته باشید عبارت موجود در مثال بالا برای شما عجیب است. وظیفه ای که عبارت لامبدا در مثال بالا دارد این است که هر عدد موجود در منبع داده را به نتیجه پرس و جو اضافه می کند. به این نکته توجه کنید که پرس و جو نتایج را بدون تغییر آنها بر می گرداند. اجازه دهید عبارت لامبدا در مثال قبلی را به شکل مفید تری تغییر دهیم.

int[] numbers = { 1, 2, 3, 4, 5 };

var result = numbers.Select(n => n + 1);

foreach(var n in result)
{
    Console.Write(n + " ");
}
2 3 4 5 6

عبارت لامبدا در مثال بالا هر عدد موجود در منبع داده را بدست آورده سپس یک واحد به آن اضافه می کند و در آخر آن را به نتیجه پرس و جو اضافه می کند. بیشتر متدهای موجود در فضای نامی System.Linq خروجی از نوع IEnumerable<T> دارند. این ویژگی به شما این امکان را می دهد که متدها را به صورت زنجیره ای فراخوانی کنید. به عنوان مثال ، کد زیر را صرف نظر از متدهای جدید آن در نظر بگیرید.نکته مهمی که در خط زیر وجود دارد فراخوانی زنجیره ای متدهای LINQ است.

var result = numbers.Where(n => n > 3).OrderBy(n => n).Select(n => n);

در این درس به شما نحوه ی استفاده از متد Select()آموزش داده شد.متدهای زیادی باقی مانده است که در درس های بعدی به آن پرداخته می شود.
حالا شما می توانید نتایج بهتری را با استفاده از متد Select() بدست آورید ، ولی نکته ی مهم این است که حالا شما می توانید از شکل متدی LINQ نیز برای پرس و جو از منبع داده استفاده کنید. در واقع کامپایلر برای پرس و جو از منبع داده از شکل متدی استفاده می کند. استفاده از عبارات پرس و جو برای پرس و جو از منبع داده فقط لایه ای برای فراخوانی ساده تر متد های الحاقی است. به عنوان نمونه ، عبارت پرس و جوی زیر را در نظر بگیرید :

var result = from p in persons
             where p.Age >= 18
             order by p.Name
             select p.FirstName + " " + p.LastName;

در زمان کامپایل عبارت پرس و جوی بالا به دنباله ای از متدهای توسعه یافته که در فضای نامی System.Linq قرار دارند تبدیل می شود. کد واقعی که کامپایلر از آن برای پرس و جو از منبع داده استفاده می کند به شکل زیر است :

var result = persons.Where(p => p.Age >= 18)
                    .OrderBy(p => p.Name)
                    .Select(p => p.FirstName + " " + p.LastName);

همانطور که میبینید متدها به صورت زنجیره ای فراخوانی شده اند. این به این دلیل است که هر کدام از متدها خروجی از نوع IEnumerable<T> دارند. بعد از فراخوانی متد Where() ، از متد OrderBy() بر روی خروجی داده ها و سپس بر روی مجموعه جدید از متد Select() استفاده کرده ایم.

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

لطفا اگر نظر، پیشنهاد و یا انتقادی در باره مطلب بالا دارید در قسمت زیر و اگر سوالی دارید در بخش پرسش و پاسخ مطرح بفرمایید.

  1. امیر ع پاسخ دادن

    سایت عالی ای هست. ممنون

    • یونس ابراهیمی پاسخ دادن

      سلام،ممنون، به دوستان معرفی بفرمایید

  2. talebpour پاسخ دادن

    سلام

    معنی این عبارت چیست؟
    p => p.Age >= 18

    • یونس ابراهیمی پاسخ دادن

      یعنی اشیایی (اشخاصی) رو انتخاب کن که سنشون بزرگتر مساوی ۱۸ باشه