تا اینجا (1 و 2 و 3 و 4 و 5 و 6 و 7) مطالب نسبتا مفصلی راجع به CLR ارائه شده. تو این قسمت هم درباره یکی دیگه از قسمتهای مرتبط با CLR به نام CLS یا Common Language Specification صحبت میشه.
تکنولوژی COM به اشیای تولیدشده تو زبانهای مختلف اجازه ارتباط با هم رو میده. به شکلی مشایه، CLR تمام زبانهای برنامه نویسی رو با هم مجتمع کرده و اجازه میده تا اشیای ایجاده شده توسط یه زبان برنامه نویسی، تو یه زبان برنامه نویسی کاملا متفاوت، همانند اشیای تولید شده تو همون زبان رفتار کنه. این فرایند بخاطر مجموعه ای استاندارد از انواع، متادیتا و نیز محیط اجرای مدیریت شده و مشترک امکانپذیر شده.
با اینکه این تجمیع و زبان های برنامه نویسی مختلف و یکسان سازی رفتارها هدفی بسیار جالب و فوق العاده به نظر میرسه، اما در عمل رفتارها و ویژگیهای گوناگون موجود بین زبانهای برنامه نویسی مختلف باعث تفاوت بسیار زیاد بین این زبانها میشه. مثلا در برخی از زبانهای برنامه نویسی case-sensivity وجود نداره، و یا برخی دیگر از اعداد بی علامت (unsigned)، یا overload اپراتورها و متدها پشتیبانی نمیکنن.
بنابراین اگه استفاده از یه کتابخونه تو زبانهای مختلف برنامه نویسی مدنظر باشه، بنابراین تنها از امکانات و ویژگی هایی که تو تمام زبانهای برنامه نویسی موردنظر پشتیبانی میشه، باید استفاده کرد. برای رسیدن به این هدف، مایکروسافت مشخصه هایی رو تحت نام CLS تهیه کرده تا تولیدکنندگان کامپایلرهایی که CLR رو هدف قرار میدن، ملزوم به رعایت یکسری حداقل ها میکنه تا به نوعی استانداردی برای تولید کتابخانه های این چنینی (قابل اجرا و استفاده تو تمام زبانها) وجود داشته باشه. به این اپلیکیشن ها اصطلاحا CLS-compliant یا سازگار با CLS میگن.
البته CLR ویژگیها و امکاناتی بسیار بیشتر از اونچه که تو CLS آورده شده رو پشتیبانی میکنه، بنابراین اگه کاربرد چند زبانی در یه برنامه مطرح نباشه، میشه بدون توجه به CLS انواع و اپلیکیشنهایی کامل و پرامکانات تولید کرد که تنها محدود به محدودیتهای زبان برنامه نویسی موردنظر باشن. در عمل CLS شامل قوانینی میشه که تنها اعضا و اجزای قابل دسترس از بیرون نوع و اسمبلی مربوطه (مثل public و protected) رو محدود میکنه.
تصویر زیر بیشتر مفاهیم ارائه شده تو این قسمت رو خلاصه میکنه:
همونطور که تو تصویری بالا مشخصه، بیشتر زبانهای برنامه نویسی موجود تنها بخشی از امکانات CLR/CTS رو فراهم میکنن، تنها IL تمامی امکانات موجود رو پشتیبانی میکنه، و CLS تنها بخش بسیار کوچکی از این ویژگی ها رو در بر داره که تمامی زبانهای برنامه نویسی که CLR رو هدف قرار میدن باید داشته باشن.
بنابراین اگه یه نوع تو یه زبان برنامه نویسی تولید میشه و قراره تو یه زبان برنامه نویسی دیگه استفاده بشه، اعضای public و protected اون باید تنها از امکاناتی که منطبق بر CLS هستن استفاده کنن. اگه این اصل رعایت نشه، این اعضا ممکنه در دسترس سایر برنامه نویسا قرار نگیره.
تو مثال زیر یه کلاس منطبق بر CLS تعریف و تولید شده، هرچند که شامل برخی قسمتهای غیرمنطبق هم هست و باعث میشه تا کامپایلر #C برای اونا warning صادر کنه.
using System; // Tell compiler to check for CLS compliance [assembly: CLSCompliant(true)] namespace SomeLibrary { // Warnings appear because the class is public public sealed class SomeLibraryType { // Warning: Return type of 'SomeLibrary.SomeLibraryType.Abc()' // is not CLS-compliant public UInt32 Abc() { return 0; } // Warning: Identifier 'SomeLibrary.SomeLibraryType.abc()' // differing only in case is not CLS-compliant public void abc() { } // No warning: this method is private private UInt32 ABC() { return 0; } } }
تو این قطعه کد، اولین نکته استفاده از خاصیت [(assembly: CLSCompliant(true] برای اسمبلی مربوطه هست. همونطور که به نظر میرسه، این خاصیت به کامپایلر میگه که تمامی اعضای از بیرون در دسترس (public و protected) باید منطبق بر CLS باشن و درواقع نباید شامل قسمتهایی باشن که مانع دسترسی به اونا تو سایر زبانهای برنامه نویسی بشه.
با کامپایل این کد، کامپایلر #C دو warning تولید میکنه. اولین هشدار برای نوع برگشتی متد Abc، یعنی UInt32 یا عدد صحیح 32 بینی بی علامت یا فقط مثبت، صادر میشه. این نوع منطبق بر CLS نیست، یعنی تمام زبانهای برنامه نویسی از این نوع پشتیبانی نمیکنن. دومین هشدار مربوط به وجود دو عضو قابل دسترس از بیرونه که تنها تو بزرگ یا کوچک بودن حروف نامشون با هم فرق دارن (متدهای Abc و abc). همه زبانهای برنامه نویسی از case-sensitive بودن نام اعضا پشتیبانی نمیکنن و بنابراین استفاده از این امکان منطبق بر CLS نیست. البته متد سوم یعنی ABC بدلیل اینکه از بیرون در دسترس نیست تو این هشدار سهمی نداره.
جالبه که با حذف سطح دسترسی public از تعریف کلاس، هر دو هشدار صادره در زمان کامپایل حذف میشن، چون سطح پیشفرض تعریف یه نوع، internal هست و برای انواعی که سطح دسترسی تعریف نکرده باشن بکار میره. بنابراین با این تغییر، کلاس SomeLibraryType از دسترسی سایر برنامه ها خارج شده و بنابرین مشکلی با CLS نخواهد داشت.
برای دیدن اطلاعات کاملتر درباره CLS و مباحث Cross-Language به اینجا یه سری بزنین.
تو CLR، اعضای یه نوع یا field (فیلد یا data) هستن یا method (متد یا رفتار یا behavior). بنابراین تمامی زبانهای برنامه نویسی ای که CLR رو هدف قرار میدن، باید قابلیت دسترسی به فیلدها یا فراخوانی متدها رو داشته باشن. البته برخی از فیلدها و متدها با یه روش خاصی استفاده میشن. درواقع برای راحتی بیشتر برنامه نویسی، زبانهای برنامه نویسی مختلف روش ها و الگوهای خاصی برای استفاده از این دو عضو فراهم میکنن. مثلا زبانهای برنامه نویسی مفاهیم و ساختارهایی چون enum، آرایه، پراپرتی، ایندکسر، delegate، ایونت، constructor و finalizer، و operator overloading و conversion operator و ... رو فراهم میکنن. در زمان کامپایل، این وظیفه کامپایلره که این مفاهیم و ساختارها رو به فیلدها و یا متدهای متناظر مناسب تبدیل کنه تا CLR بتونه از اونا استفاده کنه.
نوع زیر که شامل قسمتهای مختلفی چون constructor و finalizer و operator overload و property و indexer و event هست، برای نمونه آورده شده. دقت کنید که قطعه کد زیر فقط برای اینکه کامپایل بشه اینجا آورده شده و به هیچ وجه نحوه صحیح پیاده سازی یه نوع رو نشون نمیده.using System; internal sealed class Test { // Constructor public Test() { } // Finalizer ~Test() { } // Operator overload public static Boolean operator ==(Test t1, Test t2) { return true; } public static Boolean operator !=(Test t1, Test t2) { return false; } // An operator overload public static Test operator +(Test t1, Test t2) { return null; } // A property public String AProperty { get { return null; } set { } } // An indexer public String this[Int32 x] { get { return null; } set { } } // An event public event EventHandler AnEvent; }
وقتیکه کامپایلر این کد رو به IL تبدیل میکنه، نتیجه تنها شامل تعدادی فیلد و متد خواهد بود. میشه این مورد رو با بررسی اسمبلی تولید شده توسط ابزار ILDasm.exe آزمایش کرد. تصویر زیر محتویات اسمبلی ای که حاوی این نوعه رو تو ILDasm.exe نشون میده:
جدول زیر چگونگی تبدیل اعضای مختلف به فیلد و متد در زمان کامپایل رو نشون میده.
عضو | نوع عضو | معادل تو زبان برنامه نویسی |
---|---|---|
AnEvent | Field | Event |
.ctor | Method | Constructor |
Finalize | Method | Finalizer |
add_AnEvent | Method | Event add accessor method |
remove_AnEvent | Method | Event remove accessor method |
get_AProperty | Method | Property get accessor method |
set_AProperty | Method | Property set accessor method |
get_Item | Method | Indexer get accessor method |
set_Item | Method | Indexer set accessor method |
op_Addition | Method | + operator |
op_Equality | Method | == operator |
op_Inequality | Method | != operator |
اون قسمتهایی که تو جدول بالا آورده نشده، یعنی class. و custom. و AnEvent و AProperty و Item، برای شناسایی متادیتا و فراهم کردن اطلاعات لازم برای اجرا، تولید شدن و در عمل مستقیما به هیچیک از اعضای نوع تعریف شده مرتبط نیستن.
.: در قسمت بعد درباره استفاده از کدهای مدیریت نشده بحث میشه.
CLR به زبان ساده - قسمت اول: پیشگفتار
CLR به زبان ساده - قسمت دوم: اسمبلی
CLR به زبان ساده - قسمت سوم: بارگذاری
CLR به زبان ساده - قسمت چهارم: اجرا
CLR به زبان ساده - قسمت پنجم: IL و بررسی کد
CLR به زبان ساده - قسمت ششم: NGen.exe
CLR به زبان ساده - قسمت هفتم: FCL و CTS
CLR به زبان ساده - قسمت هشتم: CLS
CLR به زبان ساده - قسمت نهم: کد مدیریت نشده
:.