آموزش گام به گام #C (جلسه چهاردهم: معرفی delegateها و رویدادها)
1398/01/18 14:39 , میلاد صاحب نظر

آموزش گام به گام #C (جلسه چهاردهم: معرفی delegateها و رویدادها)

گاهی نوشتن منطق‌های پیچیده و تو در تو همچون if/then/else یا switch هم نظم و ترتیب کدها را به هم می‌ریزند و هم درک کدها را مشکل‌تر می‌کنند. گاهی خود #C روش‌های ساده‌تری برای انجام کارهای پیچیده ارائه می‌دهد. با ما همراه باشید!

جلسه اول: آغاز کار با #C جلسه ششم: namespaceها جلسه یازدهم: اندیس گذار یا indexerها جلسه شانزدهم: استفاده از اتریبیوت‌ها جلسه بیست و یکم: متدهای بی‌نام یا anonymous
جلسه دوم: عملگرها، نوع‌ها و متغیرها جلسه هفتم: مقدمه‌ای بر کلاس‌های #C جلسه دوازدهم: ساختار یا structها جلسه هفدهم: enumها جلسه بیست و دوم: موضوعاتی در مورد نوع در #C
جلسه سوم: عبارات کنترلی - گزینشی جلسه هشتم: وراثت کلاس در #C جلسه سیزدهم: واسط یا interfaceها جلسه هجدهم: عملگرهای overloading جلسه بیست و سوم: کار با نوع‌های nullable
جلسه چهارم: عبارات کنترلی - حلقه‌ها جلسه نهم: چندریختی جلسه چهاردهم: مقدمه‌ای بر delegateها و رویدادها جلسه نوزدهم: کپسوله‌سازی  
جلسه پنجم: متدها جلسه دهم: ویژگی یا propertyها جلسه پانزدهم: مقدمه‌ای بر کنترل خطا یا exception جلسه بیستم: مقدمه‌ای بر generic collectionها  

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

  • درک اینکه یک delegate چیست.
  • درک اینکه یک رویداد چیست.
  • پیاده‌سازی Delegateها.
  • اجرای رویدادها.

Delegateها

در طول جلسات قبلی، آموختید که چگونه می‌توان نوع‌های رفرنسی را با استفاده از ساختارهای زبان (ساختارهایی مثل کلاس‌ها و واسط‌ها) پیاده‌سازی کرد.

این نوع‌های رفرنسی به شما اجازه می‌دهند نمونه‌ها یا instanceهایی از اشیاء ایجاد کرده و از آن‌ها به روش‌های خاصی استفاده کنید تا به اهداف توسعه نرم ‌افزار خود برسید.

کلاس‌ها برای شما امکان ایجاد اشیائی را فراهم می‌کنند که حاوی اعضای دارای اتریبیوت یا رفتار می‌باشند.

واسط‌ها این امکان را برای شما فراهم می‌کنند که بتوانید مجموعه‌ای از اتریبیوت‌ها و رفتارهایی را تعریف کنید که همه اشیائی که این مجموعه‌ها را پیاده‌سازی می‌کنند، به صورت عمومی به نمایش گذارده می‌شوند.

امروز، قصد دارم یک نوع رفنرسی جدید به نام delegate را به شما معرفی کنم.

Delegate یکی از عناصر زبان #C است که به شما اجازه می‌دهد یک متد را رفرنس کنید. اگر تجربه برنامه‌نویسی با C یا ++C را داشته باشید، این عنصر برای شما آشنا خواهد بود، چون delegate اساسا یک اشاره‌گر تابع (function pointer) است.

به هر حال، توسعه‌دهندگانی که از زبان‌های دیگر استفاده کرده‌اند ممکن است تعجب کنند و بپرسند که چرا من باید یک تابع را رفرنس کنم؟ پاسخ این سوال ساده است: این روش برای شما حداکثر انعطاف‌پذیری لازم برای پیاده‌سازی هر گونه تابع در رانتایم را فراهم می‌کند.

به روش فعلی خود برای استفاده از متدها فکر کنید. شما الگوریتمی می‌نویسید که وظیفه‌اش را با دست‌کاری مقادیر متغیرها و فراخوانی متدها مستقیما با نام آن‌ها انجام می‌دهد.

حالا، اگر بخواهید الگوریتمی بنویسید که خیلی انعطاف‌پذیر، قابل استفاده مجدد و دارای قابلیت پیاده‌سازی توابع مختلف مورد نیاز در طول برنامه باشد، آن موقع چه کار می‌کنید؟

علاوه بر این، فرض کنیم که این الگوریتم شامل چند نوع‌ ساختمان داده باشد که قصد دارید آن‌ها را مرتب‌سازی کنید، اما همچنین قصد دارید این ساختمان‌های داده نوع‌های مختلف را نیز در خودشان نگه دارند.

اگر ندانید نوع‌ها دقیقا چه هستند، چگونه می‌توانید در مورد انتخاب یک روتین مقایسه‌ای مناسب تصمیم‌گیری کنید؟

شاید بتوانید از یک ساختار if/then/else یا switch برای کنترل نوع‌های شناخته شده و معروف استفاده کنید، اما این روش‌ها بسیار محدود بوده و برای تشخیص نوع، باید در آن‌ها منطق سخت و قوی‌ای بنویسید.

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

ه هر حال، چون این جلسه در مورد Delegateها است، ما از روش و راه حل delegate استفاده می‌کنیم که فوق‌العاده است.

می‌توانید این مشکل را با انتقال یک delegate به الگوریتم خود و اجرای متد درون آن (متدی که delegate به آن اشاره می‌کند) برای انجام عملیات مقایسه برطرف کنید. چنین عملیاتی در لیست ۱-۱۴ انجام شده است.

مثال delegate در #C

لیست ۱-۱۴. تعریف و پیاده‌سازی یک delegate: SimpleDelegate.cs

اولین کاری که برنامه در این مثال از delegate در #C انجام می‌دهد این است که یک delegate تعریف می‌کند. تعاریف delegate چیزی شبیه به تعاریف متدها هستند، به جز اینکه آن‌ها دارای تنظیم‌کننده یا modifier با کلیدواژه delegate هستند، با سمی کالن خاتمه می‌یابند و هیچ پیاده‌سازی ندارند.

در زیر، نحوه تعریف delegate در لیست ۱-۱۴ را مشاهده می‌کنید.

این تعریف delegate، امضای یک متد کنترل‌کننده delegate را تعریف می‌کند که این delegate به آن اشاره می‌کند. متد کنترل‌کننده delegate، برای Comparer delegate، می‌تواند هر نامی داشته باشد، اما حتما باید دارای اولین و دومین پارامتر نوع شیء بوده و یک نوع int بازگرداند.

متد زیر از لیست ۱-۱۴ یک متد کنترل‌کننده delegate را نشان می‌دهد که با امضای Comparer delegate مطابقت دارد.

نکته: متد CompareFirstNames نوع رشته یا String را فراخوانی می‌کند. این متد، نام اول FirstName) property)های دو نمونه Name را با هم مقایسه می‌کند. لطفا اجازه ندهید که پیاده‌سازی این متد در یادگیری نحوه عملکرد delegate تداخل ایجاد کنید.

چیزی که شما باید روی آن تمرکز کنید این است که CompareFirstNames یک متد کنترل‌کننده است که یک Delegate می‌تواند به آن اشاره کند، مهم نیست کد داخل آن متد چه باشد.

برای استفاده از یک Delegate، باید یک نمونه یا instance از آن ایجاد کنید. نمونه ایجاد شده در این مثال دقیقا همانند ایجاد نمونه از یک کلاس است و دارای یک پارامتر برای شناسایی متد کنترل‌کننده مناسب Delegate می‌باشد، که در زیر مشاهده می‌کنید:

Delegate که نام آن در این مثال CMP است، به عنوان پارامتری برای متد ()sort استفاده می‌شود، که درست همانند یک متد طبیعی، از آن استفاده می‌شود. روش انتقال Delegate به متد ()Sort به عنوان یک پارامتر در کد زیر نمایش داده شده است.

با استفاده از این تکنیک، می‌توان هر متد کنترل‌کننده Delegate را در رانتایم به متد ()Sort منتقل کرد. برای مثال، می‌توانید یک کنترل‌کننده متد به نام ()CompareLastNames تعریف کنید، با آن یک نمونه جدید Compare delegate نمونه‌سازی کنید و Delegate جدید را به متد ()Sort منتقل کنید.

رویدادها

برنامه‌های کنسول قدیمی به این صورت عمل می‌کنند که منتظر می‌مانند تا کاربر یک کلید را فشار دهد یا یک دستور تایپ کند و کلید enter را بزند. سپس، چند عملیات از پیش تعریف شده را انجام می‌دهند و در آخر یا از برنامه خارج شده یا به ابتدای اجرای برنامه بازمی‌گردند.

این روش موثر است، اما بسیار غیر منعطف است چون همه چیز در آن باید کد نویسی شود و از یک روش اجرای ثابت و بدون تغییر پیروی شود. در مقابل، برنامه‌های GUI مدرن با یک مدل رویداد محور عملیات انجام می‌دهند.

در نتیجه، چند رویداد در سیستم اتفاق می‌افتند و ماژول‌های مورد نظر مشخص می‌شود تا عکس‌العمل مناسب را نشان دهند. در Windows Formها، هیچ مکانیزم نمونه‌برداری برای جمع‌آوری منابع وجود ندارد و لازم نیست یک حلقه بنویسید که منتظر وارد شدن یک ورودی باشد. همه چیز با استفاده از رویدادها درون سیستم نوشته شده است.

رویداد در #C در واقع یک عضو کلاس است که این عضو، هر موقع رویداد مناسب و مخصوص آن پیش آمد، فعال می‌شود. هر کلاسی، به خصوص کلاسی که رویداد در آن تعریف شده است، می‌تواند یکی از متدهایش را برای رویداد ثبت کند. این کار از طریق delegate انجام می‌شود.

Delegate امضای متدی که برای رویداد ثبت شده است را مشخص می‌کند. Delegate می‌تواند یکی از delegateهای از پیش تعریف شده در NET. باشد یا می‌تواند یک delegate باشد که خودتان تعریف کرده باشید.

هر کدام مناسب‌تر بود را برای یک رویداد انتخاب و ثبت کنید. این delegate در واقع متدی را ثبت می‌کند که وقتی رویداد اتفاق می‌افتد، فراخوانی می‌شود. لیست ۲-۱۴ دو روش مختلف برای پیاده‌سازی رویدادها را نمایش می‌دهد.

لیست ۲-۱۴. تعریف و پیاده‌سازی رویدادها: Eventdemo.cs

نکته: اگر از ویژوال استودیو یا یک IDE دیگر استفاده می‌کنید، قبل از کامپایل کدهای لیست ۲-۱۴ به یاد داشته باشید که رفرنس‌ها را به System.Drawing.dll و System.Windows.Forms.dll اضافه کنید یا کد را به یک پروژه Windows Form اضافه کنید.

آموزش نحوه عملکرد ویژوال استودیو یا IDEهای دیگر از دامنه بحث این دوره خارج است.

شاید توجه کرده باشید که لیست ۲-۱۴ یک برنامه Window Form است. البته ما Windows Form را در این دوره پوشش نداده‌ایم، بنابراین اگر می‌خواهید گیج نشوید باید اطلاعات کافی در مورد برنامه‌نویسی #C به صورت کلی داشته باشید.

برای کمک به شما، توضیح مختصری در مورد برخی بخش‌هایی که ممکن است با آن‌ها آشنایی نداشته باشید ارائه می‌دهم.

کلاس Event demo از Form ارث‌بری می‌کند، که این فرم ضرورتا یک Windows Form است. این فرم به صورت خودکار، تمام ویژگی‌های یک Windows Form (از جمله جایگاه عنوان، کلید‌های مینیمم/ماکسیمم/بستن، منوی سیستم و مرزها) را برای شما فراهم می‌کند. ارث‌بری خیلی ویژگی  قدرتمندی است، این‌طور نیست؟

روشی که یک برنامه Window Form آغاز می‌شود این است که متد ()Run از شیء Application که static هم هست  فراخوانی می‌شود و دارای رفرنسی به سمت شیء فرم (به شکل پارامتر) است. با این کار، تمام مراحل بعدی آغاز می‌شوند، GUI نمایش داده می‌شود و اطمینان حاصل می‌کند که رویدادها به صورت مناسب اجرا شوند.

ابتدا اجازه دهید رویداد سفارشی را بررسی کنیم. در زیر تعریف رویداد را مشاهده می‌کنید، که همان‌طور که می‌دانید این تعریف عضوی از کلاس Event demo است. این رویداد با کلیدواژه Event، یک نوع delegate و یک نام برای رویداد تعریف شده است.

پس، هر موقع خواستید از یک رویداد استفاده کنید، باید یک Delegate برای آن رویداد ثبت کنید. در خط بعدی، ما یک delegate از نوع Startdelegate داریم که برای پذیرفته شدن در رویداد تعریف شده است و به رویداد Startevent متصل شده است.

عملگر =+ یک delegate را برای یک رویداد ثبت می‌کند. برای عدم ثبت یا حذف یک رویداد، از عملگر =- استفاده می‌شود.

اجرای یک رویداد درست همانند فراخوانی یک متد است، که در زیر مشاهده می‌کنید:

این روش کامل پیاده‌سازی رویدادها بود، به شکلی که خودتان رویداد و Delegate را تعریف کنید. به هر حال، بسیاری از برنامه‌نویسی‌های رویدادی که در آینده انجام خواهید داد، از طریق رویدادها و Delegateهای از پیش تعریف شده خواهند بود.

این امر ما را به سمت کد رویداد دیگری سوق می‌دهد که در لیست ۲-۱۴ مشاهده می‌کنید، در این کد ما یک Delegate به نام EventHandler را به رویداد Click از کلید متصل می‌کنیم.

رویداد click از قبل به کلاس Button تعلق داشته است و تنها کاری که ما باید انجام دهیم این است که در هنگام ثبت delegate، به آن اشاره کنیم یا رفرنس دهیم. به طور مشابه،delegate EvenntHandler نیز از قبل در System Namespace از کتابخانه کلاس NET Framework. موجود بوده است.

واقعا تنها کاری که شما انجام می‌دهید این است که متد فراخوانی خود (یعنی متد کنترل‌کننده Delegate) را تعریف می‌کنید و این متد زمانی فراخوانی می‌شود که کاربر روی کلید Me کلیک کند.

متد ()OnClickMeClicked که در زیر نمایش داده شده است، با امضای EventHandler delegate تطابق دارد که می‌توانید این متد را در رفرنس کتابخانه کلاس NET Framework. جستجو کنید.

هر وقت روی کلید ClickMe با موس کلیک شود، رویداد Click اجرا می‌شود که در نتیجه متد ()OnClickMeClicked فراخوانی می‌شود. کلاس Button اجرای رویداد Click را اداره می‌کند و شما دیگر کاری لازم نیست انجام دهید.

چون استفاده از رویدادها و Delegateهای از پیش تعریف شده خیلی آسان است، پس هر جا به رویداد یا Delegate نیاز پیدا کردید بد نیست ابتدا بررسی کنید که آیا در کتابخانه‌ها وجود دارد یا خیر، اگر نبود خودتان ایجادشان کنید.

خلاصه

با این حساب، این جلسه که در مورد معرفی delegateها و رویدادها بود پایان می‌یابد. یاد گرفتید که چگونه Delegateها را تعریف و پیاده‌سازی کنید، که یک متد رانتایم پویا برای فراخوانی برخی سرویس‌ها و خدمات فراهم می‌کنند. همچنین آموختید که چگونه رویداد‌ها را تعریف کنید و از آن‌ها در سناریوهای مختلف استفاده کنید.

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

منبع: C#-Station

جلسه بعد                                                                جلسه قبل

 مطالب مرتبط

 مقدمه ای بر زبان برنامه نویسی #C و پلتفرم NET Framework.
7 دلیل منطقی برای آموختن #C
 طبقه بندی زبان های برنامه نویسی
به دست آوردن Exceptionها در #C و یافتن همه خطاها
 LINQ(زبان جستجوی یکپارچه)
برنامه نویسی شیءگرا چیست؟

از آخرین دوره های آموزشی و تخفیف ها مطلع شوید

با تکمیل فرم زیر ، از اخبار و اطلاعات به روز برنامه نویسی و تکنولوژی عقب نمانید

آخرین مطالب

آموزش جامع SQL Server (جلسه ۱۲)
آموزش جامع SQL Server (جلسه ۱۲)

دستور UPDATE در SQL Server برای تغییر داده‌های موجود در یک جدول، از دستور UPDATE به شکل زیر استفاده ...

آموزش جامع SQL Server (جلسه ۱۵)
آموزش جامع SQL Server (جلسه ۱۵)

دستور DROP TABLE در SQL Server گاهی، لازم است یک جدول که دیگر استفاده‌ای ندارد را حذف کنید. برای ...

آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)
آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)

بخش اول از آخرین مبحث دوره جامع آموزش SQL Server در جلسه قبلی بررسی شد. این مبحث که ...

آخرین دیدگاه ها

دیدگاه خود را درباره این پست بنویسید

فرم ارسال نظرات