بررسی عملوندهای جستجو در LINQ

فکر همه‌ چیز را کرده‌اند

در شماره گذشته، با LINQ به‌صورت پایه‌ای آشنا شدیم. در این شماره قصد داریم تا با عملگرهای جستجو آشنا شویم.
کد خبر: ۳۲۷۳۵۱

فرض کنید ما بخواهیم یک رشته را برعکس کنیم، کلاس string چنین متدی در اختیار ما نمی‌گذارد. از طرفی ما به سورس کلاس string دسترسی نداریم که چنین متدی به آن اضافه کنیم. تنها راهی که می‌ماند این است که شما یک کلاس جدا بنویسید. این کلاس یک متد استاتیک دارد که یک رشته را می‌گیرد و معکوس آن‌را برمی‌گرداند. این روش کاملا منطقی و درست است ولی خب، ما می‌خواهیم کد زیباتری داشته باشیم و این متد به عنوان جزئی از کلاس string باشد، حال چه باید بکنیم؟ جواب در یکی از ویژگی‌هایی است که در#C نگارش سوم به‌وجود آمده است:‌ Extension-Method یا متد افزوده، کد زیر را ببینید:

public static string reverse(this string text);

این خط کد یک متد افزوده را برای کلاس string معرفی می‌کند، یعنی متد reverse جزئی از کلاس string شناخته می‌شود. نکته‌ای که باید به آن دقت کنیم این است که کلاسی که این متد در آن تعریف می‌شود باید static باشد. بسیار خب ما توانستیم یک متد برای کلاس string تعریف کنیم. همان‌طور که پیش از این گفتیم، LINQ روی یک مجموعه داده فعالیت می‌کند. ما می‌دانیم که تمامی مجموعه‌های داده در net. اینترفیس «IEnumerable«T را پیاده کردند (T نوع داده را مشخص می‌کند مثلا «IEnumerable«int)، پس می‌توانیم بگوییم که هر متدی که برای این اینترفیس به‌صورت متد افزوده تعریف شود می‌تواند روی همه نوع مجموعه داده‌ای کاربرد داشته باشد. قبل از ما برنامه‌نویس‌های دات نت این‌کار را انجام داده‌اند و تعدادی متد را برای این اینترفیس پیاده کردند و ما قصد داریم چندتا از آن‌ها را بررسی کنیم. به این متدها اصطلاحا می‌گویند «عملگرهای جستجو» (Query Operators). اولین عملگری که قصد داریم آن‌را بررسی کنیم where است و شکل کلی آن به‌صورت زیر است:

public static IEnumerable«T» Where«T»( this IEnumerable«T» source, Func«T, bool» predicate);

تنها نکته برای این عملگر Func است که ناآشنا به‌نظر می‌رسد. Func یک delegate است و یک متد را نشان می‌دهد که یک T می‌گیرد (T به نوع داده‌های ذخیره شده در source اشاره می‌کند) و یک مقدار bool را برمی‌گرداند.

به این صورت

public bool Check(T type) {return type is string};

این متد مشخص می‌کند که type از نوع string است یا خیر. می‌توان اشاره‌گر این تابع را به predicate در عملگرwhere داد، در نتیجه کدی به این ‌صورت نوشته می‌شود:

Func«string,bool» checker = Check;

string[] names = {“a”,“b”};

names.Where(checker);

باز هم بهتر است بگوییم که برنامه‌نویس‌های دات‌نت فکر اینجا را هم کرده‌اند و این امکان را به ما داده‌اند که بتوانیم کد ساده‌تری بنویسیم. می‌توان کد بالا را با استفاده از عبارت لامبدا بازنویسی کرد:‌

string[] names = {“a”,“b”};

names.Where(name =» name is string);

می‌بینید که کد به‌مراتب کوچکتری به‌دست آمد. حال متوجه شدیم که عملگر where دقیقا چه‌کاری انجام می‌دهد، یک شرط را برای یک مجموعه اعمال می‌کند و داد‌ه‌هایی که در این شرط صدق می‌کنند را برمی‌گرداند:

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

public static IEnumerable«S» Select«T, S»(this IEnumerable«T» source, Func«T, S» selector);

تقریبا شبیه به where است ولی با این تفاوت که این عملگر روی داده‌هایی از نوع T اعمال می‌شود و مجوعه‌ای از نوع S برمی‌گرداند:

S هر چیزی می‌تواند باشد، باز برمی‌گردیم به یک ویژگی جدید در C# 3.0 به نام Anonymous Type یعنی داده‌هایی که در یک لحظه به‌وجود می‌آیند و هیچ ساختار مشخصی ندارند بلکه نشان دهنده یک مدل دیتا هستند این نوع داده در حین اجرا به‌وجود می‌آید. به مثال زیر توجه کنید:

names.Select(name=»new { Name = name});

این کد برای هر عضو از مجموعه names یک Anonymous type، که یک کلاس شامل یک ویژگی به‌نام Name است را برمی‌گرداند. اما ما این نوع داده را نمی‌شناسیم پس چگونه باید به کامپایلر بگوییم نوع داده چیست؟ برای این‌کار از کلمه کلید به‌صورت زیر varاستفاده می‌کنیم:

var res = names.Select(name=»new { Name = name });

عملگر بعدی که قصد داریم آن‌را توضیح دهیم OrderBy است:

public static IOrderedSequence«T» OrderBy«T, K»(this IEnumerable«T» source, Func«T, K» keySelector);

این عملگر داده‌هایی از نوع T را بر اساس متد K صورت می‌کند، مانند مثال زیر:

names.OrderBy(name=»name);

امیربهاالدین سبط‌الشیخ

newsQrCode
ارسال نظرات در انتظار بررسی: ۰ انتشار یافته: ۰

نیازمندی ها