Closure

سلام دوستان!

چند وقتی بود که برایتان چیزی ننوشته بودم. برای همین تصمیم گرفتم مطلبی در مورد Closure بنویسم. Closure در زبان‌های برنامه‌نویسی وقتی به وجود آمد که اجازه دادند یک function در یک function دیگر ساخته شود. در سی شارپ delegate یک مدل از همین نوع function هاست. یا در Javascript می‌توانم بگویم functionی که می‌سازیم همین‌طور است. به طور کلی جایی که بتوانیم یک function را تعریف کنیم و مقدار آن function را برگردانیم ممکن است Closure به وجود بیاید. به مثال زیر دقت کنید:

همان‌طور که مشاهده می‌کنید در مثال بالا داخل someFunctionThatReturnFunction یک function دیگر را بازمی‌گردانیم و در ادامه بعد از اتمام این function اقدام به صدازدن functionی که درون function ذکرشده وجود داره می‌کنیم.

تا اینجا که همه چیز به نظر عادی و خوب می‌رسد اما اجازه بدهید مسئله رو کمی پیچیده تر بکنیم:

همان‌طور که می‌بینیم این بار در someFunctionThatReturnFunction یک variable تعریف کردیم و در ادامه داریم از آن variable در function استفاده می‌کنیم. شاید سوال برایتان پیش بیاد که این مسئله چه مشکلی می‌تواند داشته باشد. جواب هم این است که ما در زبان‌های برنامه‌نویسی مفهومی داریم به اسم Scope که همان‌طور که می‌دانیم در Javascript ما کلا دو نوع Scope داریم یکی Global و یکی هم Function.

حالا اگر هم در مورد Scope زیاد ندانیم مهم نیست. مهم این است که بدانیم در مثال بالا فرض بر این بوده که وقتی صدازدن someFunctionThatReturnFunction تمام می‌شود دیگر هرچی Variable در آن ساختیم کارش تموم می‌شود. بهتر است بگویم قرار بود بشود. اما نکته اینجاست که این متغییر در یک Functionی استفاده ‌شده که دارد از Function اصلی خارج می‌شود و نباید حذف شود.

اینجاست که مفهوم Closure به وجود می‌آید. یک ماهیت به وجود می‌آید بین هر دفعه که آن Function اصلی رو صدا می‌زنیم و Function زیری و آن Variableی که در Function اصلی تعریف کردیم.

اگه علاقه‌مند بودید که این مبحث را به صورت عمیق‌تری در Javascript بررسی کنید در لینک زیر توضیح خوب و پیچیده ای در مورد این مطلب نوشته شده است:

http://dmitrysoshnikov.com/ecmascript/javascript-the-core-2nd-edition/#closure

در ادامه به نظرم بهتر است برویم سراغ سی شارپ و کمی بررسی کنیم ببینیم که در سی شارپ برای حل این مسئله چه کاری انجام می‌شود.

به نظر می‌رسد طراحان زبان سی شارپ روش خیلی ساده‌تری را برای حل این مسئله پیدا کردند. خوب به کد زیر دقت کنید:

همان‌طور که مشاهده می‌کنید در کد بالا نیز مانند مثال‌های ذکرشده متغیری وجود دارد که Closure شده است. حالا کد رو کامپایل می‌کنیم و در ILSpy باز می‌کنیم. در ILSpy باید کد را به صورت ILببینیم ولی برای سادگی مطلب من کد تولیدشده را به زبان سی شارپ برایتان می‌نویسم.

همان‌طور که مشاهده می‌فرمایید مسئله به صورت خیلی ساده‌تری در سی شارپ حل شده است. اگر به خاطر بیاورید در قسمت قبلی گفته شد که Closure یک ماهیت است که بین زمان اجرای Function اصلی و Function زیری و Variableی که تعریف‌شده به وجود می‌آید. زبان سی شارپ نیز وقتی به کدی می‌رسد که متغیر لازم دارد Closure شود یک کلاس تولید می‌کند (در مثال ما کلاس c__DisplayClass0_0بود) و هر دفعه که Function اصلی صدا زده می‌شود یک Instance جدید از آن درست می‌کند یعنی شروع می‌کند آن ماهیت را درست کند. از حالا به بعد هر جایی که مقدار متغییر تغییر پیدا می‌کند آن fieldی که در کلاس تعریف‌شده را تغییر می‌دهد. در نهایت هم هر موقع که با Function زیری کار داشت Method ساخته‌ شده در کلاس جدید را برمی‌گرداند.

امیدوارم مطلب مفید بوده باشد.