سی شارپ ( #C ) زبانی شیءگرا و سطح بالا از خانوادهٔ زبانهای چارچوب داتنت شرکت مایکروسافت است.
زبان سی شارپ، یک زبان برنامهنویسی چند الگویی و است و منظم شده مدلهای تابعی، امری، عمومی، شیءگرا و جز گرا و در بستر دات نت میباشد. این زبان توسط مایکروسافت و جزئی از دات نت به وجود آمد و بعداً استانداردهای ECMA و ISO را نیز در بر گرفت. سی شارپ یکی از ۴۴ زبان برنامهنویسی است که توسط زمان اجرای زبان مشترک از چارچوب داتنت پشتیبانی میشوند و در همه جا به وسیله مایکروسافت ویژوال استودیو شناخته میشود.
زبان سی شارپ با قدرت و در عین حال سطح بالایی خود توانسته توجه بسیاری از برنامه نویسان را به خود جلب کند.
این زبان برپایه سادگی، مدرن بودن، همه منظوره و شیءگرا بودن ساخته شد. آندرس هجلزبرگ، طراح زبان برنامهنویسی دلفی، سرپرستی تیم طراحان زبان سی شارپ را بر عهده داشت. این زبان دارای دستوری شیءگرا مشابه ++C است و به شدت از زبانهای جاوا و دلفینیازمندمدرک تاثیر پذیرفتهاست. در ابتدا نام این زبان COOL بود که مخفف C like Object Oriented Language بود، هر چند در ژوئیه ۲۰۰۰، زمانی که مایکروسافت پروژه را عمومی اعلام کرد، اسم آن به سی شارپ تغییر پیدا کرد. آخرین نسخه آن نسخه ۵٫۰ است که همزمان با داتنت ۴٫۵ در آگوست ۲۰۱۲ منتشر شد.
اهداف طراحی زبان
- استاندارد ECMA این اهداف طراحی زبان را برای سی شارپ بر آورده میسازد:
- سی شارپ یک زبان برنامهسازی ساده، مدرن، برای اهداف عمومی و شیءگرا است.
- به دلیل اهمیت داشتن موضوع نیرومندی و دوام و بهرهوری برنامهنویس، زبان دارای چککننده Strong Type، چککننده مرزهای آرایه، تشخیص حالتهایی که یک متغیر مقداردهی اولیه نشدهاست، قابلیت انتقال کدها و Garbage Collection خودکار است.
- این زبان برای استفاده در اجزای توسعه نرمافزار برای دستیابی به مزایای سامانههای توزیعی در نظر گرفته شدهاست.
- قابلیت انتقال برنامهنویس بسیار مهم است، خصوصاً برای آن دسته از برنامهنویسانی که با زبانهای C و C++ آشنا هستند.
- پشتیبانی از این زبان برای بینالمللی شدن بسیار مهم است.
- زبان سی شارپ برای نوشتن برنامهها برای سامانههای تعبیه شده و میزبان در نظر گرفته شدهاست، سیستمعاملهای پیچیده بسیار بزرگ گرفته تا توابع اختصاصی بسیار کوچک.
- هر چند برنامههای نوشته شده با سی شارپ طوری هستند که از لحاظ حافظه و پردازنده مورد نیاز مقرون به صرفه باشند، ولی خود زبان از لحاظ اندازه و کارایی به خوبی زبانهای C و اسمبلی نیست.
تاریخچه
در سال ۱۹۹۹، شرکت سان اجازه استفاده از زبان برنامهنویسی جاوا را در اختیار ماکروسافت قرار داد تا در سیستمعامل خود از آن استفاده کند. جاوا در اصل به هیچ پلت فرم یا سیستمعاملی وابسته نبود، ولی ماکروسافت برخی از مفاد قرار داد را زیر پا گذاشت و قابلیت مستقل از سیستمعامل بودن جاوا را از آن برداشت. شرکت سان پروندهای علیه ماکروسافت درست کرد و ماکروسافت مجبور شد تا زبان شیءگرای جدیدی با کامپایل جدید که به ++C شبیه بود را درست کند. در طول ساخت دات نت، کلاسهای کتابخانهای با زبان و کامپایلر SMC نوشته شدند. در سال ۱۹۹۹ آندرس هلزبرگ گروهی را برای طراحی زبانی جدید تشکیل داد که در آن زمان نامش Cool بود و همانند C بود با خواص شیءگرایی. ماکروسافت در نظر داشت اسم این زبان را تا آخر Cool قرار دهد، ولی به دلیل مناسب نبودن برای اهداف تجاری این کار را نکرد. در ارائه و معرفی رسمی چارچوب داتنت در PDC در سال ۲۰۰۰ این زبان به سی شارپ تغییر نام یافت و کتابخانه کلاسها و runtime در ایاسپیداتنت به سی شارپ منتقل شدند. مدیر و سرپرست طراحان در ماکروسافت آندرس هلزبرگ بود که تجربه قبلی او در طراحی Framework و زبانهای برنامه سازی++Borland، دلفی (شهر)، Turbo Pascal، ویژوال سی++ به آسانی در دستورالعملهای سی شارپ قابل رویت است و به همان خوبی در هسته CLR.
ویژگیها
برخی از تفاوتهای زبان سی شارپ با C و ++C عبارتند از:
- هیچ تابع یا متغیر سراسری(Global) وجود ندارد، تمام متدها و اعضا بایستی در داخل کلاسها تعریف شوند. این امر ممکن است، هر چند برای استفاده از متغیرها و توابع عمومی باید از متدها و متغیرها در کلاسهای عمومی استفاده کرد.
- متغیرهای عمومی، بر خلاف C و ++C، نمیتوانند بلاکهای پیوستی را در بر بگیرند.
- سی شارپ دارای یک نوع داده بولی است (bool). برخی از عبارتها مانند while و if که شرطی هستند، نیازمند یک عبارت نوع بولی هستند. همان طور که ++C نیز دارای نوع داده بولی است، این نوع داده به راحتی میتواند به یا از Integerها تبدیل شود، و عبارتی مانند (if(a نیازمند این امر است که a از یک نوع قابل تبدیل به bool یا اشاره گر باشد. کامپایلر سی شارپ برنامه نویس را در این شرایط مجبور به استفاده از عباراتی میکند که به درستی یک مقدار bool را برمیگردانند؛ بنابراین دستوری مانند (if(a = b باعث بروز خطا میشوند.(به جای = بایستی از == استفاده شود)
- در سی شارپ، اشاره گرهای به حافظه بایستی فقط در داخل بلوکهای unsafe استفاده شوند و برنامه در این حالت برای اجرا نیاز به اجازه از کاربر دارد. بیشتر دسترسی شی از طریق شی امن است که یا همیشه در حال اشاره به شی صحیح موجود است یا یک مقدار Null دارد. اشاره گری به شی به درد نخور یا بلاک حافظه رندم غیر ممکن است. اشاره گر نا امن میتواند به نمونهای از value-type، آرایه، رشته یا بلاکی که حافظه به آن داده شدهاست اشاره نماید. کدی که به عنوان نا امن علامت نخورده باشد، هنوز میتواند اشاره گرها را از سامانه بازیابی یا در آن ذخیره کند ولی نمیتواند مرجع جدیدی به آنها اختصاص دهد.
- حافظه ساماندهی شده نمیتواند صریحاً آزاد شود، ولی به طور خودکار به عنوان به درد نخور تلقی میشود. انتخاب آدرسهای به درد نخور حافظه نفوذ ناپذیر است. هم چنین سی شارپ با استفاده از عبارات، پشتیبانی مستقیمی از پایان اجباری میکند (پشتیبانی از اصطلاح Resource Acquisition Is Initialization).
- وراثت چندگانه از کلاسها در این زبان پشتیبانی نمیشود. البته یک کلاس امکان ارث بری از تعداد نامحدود واسطها را دارد. پشتیبانی نکردن از وراثت چندگانه به دلیل اهداف معماری این زبان در CLI و برای جلوگیری از پیچیدگی است. در عوض میتوان از اینترفیسهای مختلف استفاده کرد. یعنی برای یک کلاس که احتمالاً فرزند کلاسی دیگر است (ارث برده) میتوان چندین اینترفیس را پیادهسازی (Implement) نمود.
- سی شارپ بسیار typesafe تر از C++ است. تنها تبدیلات ضمنی مثل تبدیل نوع داده کوچکتر به بزرگتر یا تبدیل نوع مشتق شده به نوع پایه به طور پیش فرض و بدون خطا صورت میپذیرد. هیچ تبدیل ضمنی ای میانBooleanها و Integerها وجود ندارد و هر تبدیل user-defined بایستی به صراحت با یکی از کلمات explicit یا implicit نشانه گذاری شود. تبدیل b به a در حالتی که a یک Integer و b یک double باشد در زبان C++ مجاز است اما در سی شارپ به یک خطای زمان کامپایل منجر میشود (بایستی به صورت explicit تعریف شود)
- اعضای Enumeration در داخل محدوده شخصی خود قرار دارند.
- سی شارپ قابلیت syntactic sugar را برای توابع متداول، اکسسورها و ماجولهای کسول شده در یک کلاس به صورت ویژگیها قرار دادهاست.
اکسسورها که خاصیت نیز گفته میشوند در زبان سی شارپ قادر به کنترل دسترسی اعضا و معتبرسازی دادهها هستند.
- تمام انواع بازتابی(Reflection) و بازیابی(Recovery) قابل استفادهاست.
- در حال حاضر (۳ ژوئن ۲۰۰۸) دارای ۷۷ کلمه رزرو شدهاست.
ساختمان داده (ساختار و ذخیر سازی داده)
این کمپایلر در مقابل C یا ++C دارای ساختار بسیار متفاوتی است که دانستن آن به برنامه نویس امکان نوشتن برنامههای بسیار بهینه را خواهد داد.
رشتهها
در C و یا ++C ساختار رشته به صورت ارایهای از نوع char بود که امکان اضافه کردن به رشته را محدود میکرد به دلیل ثابت بودن طول در آغاز تعریف ولی در سی شارپ دو نوع متفاوت رشته وجود دارد؛ که یکی به صورت ارایهای با طول ثابت ۲۵۶(در عمل ۲۵۵)موجوداست (به صورت پیش فرض) و در صورتی که با کمبود جا روبرو شود فضای جدید (بزرگتر) یافته و به ان انتقال میدهد؛ ولی در نوع دوم رشتهها از لیست پیوندی اسفاده میشود.
سامانه یکپارچه شده
سی شارپ دارای یک سامانه نوع یکپارچهاست که به آن CTS میگویند. این بدان معناست که تمام انواع، شامل موارد اصلی مانند Integerها، مشتق شده از System.Object هستند. به عنوان مثال، هر نوع یک متد به نام ToString() را به ارث میبرد. بخاطر کارائی، انواع اولیه (و انواع مقداری) به طور داخلی فضایی برای آنها بر روی پشته در نظر گرفته میشود.
انواع داده
CTS دادهها را به دو نوع تقسیم میکند:
- نوع مقداری (Value Type)
- نوع مرجعی (Refrence Type)
انواع دادهای توده سادهای از داده میباشند. نمونههای انواع دادهای نه هویت مرجعی دارند و نه مفاهیم مقایسه مراجع را. برای مقایسه برابری یا عدم برابری انواع دادهای، خود مقدار دادهها را با یکدیگر مقایسه میکنیم مگر اینکه عملگرهای مشابه دوباره تعریف شده باشند. مقادیر دادههای مرجعی همیشه یک مقدار پیش فرض دارند و همیشه میتوانند ایجاد و یا کپی شوند. یکی دیگر از محدودیتهای انواع دادهای این ات که آنها نمیتوانند از یکدیگر مشتق شوند (ولی میتوانند اشتراکاتی داشته باشند) و هم چنین نمیتوانند در سازنده مقدار دهی اولیه شوند. مثالی از انواع دادهای، بعضی از انواع اولیه مانند int و float و char و System.DateTime میباشند. در مقابل، انواع مرجعی مفهوم تعریف مرجعی را دارند (که در آن هر نمونه از نوع مرجع، به طور ذاتی از دیگر نمونهها جدا میشود، حتی اگر داده هر دو نمونه یکی باشد). این دقیقاً نمونه مشابه مقایسه تساوی یا عدم تساوی دادههای مرجعی است، که در آن آزمایش برای مرجعها از دادهایها سریع تر است. در کل نه همیشه امکان تعریف نمونه مرجعی وجود دارد و نه امکان کپی یا نمایش مقادیر مقایسه دو نمونه؛ ولی به هر حال انواع مرجعی خاص میتوانند این اعمال را از طریق سازندههای عمومی یا اجرای واسطهای مشابه (مثل ICloneable یا IComparable) انجام دهند. نمونههایی از انواع مرجعی، اشیا، System.String و Sysmet.Array میباشند. هر دو نوع داده قابلیت انعطاف توسط تعریف به وسیله کاربر را دارند. در واقع وقتی ما نوع دادهای را به تابع ای ارسال میکنیم، آدرس داده نیز فرستاده میشود. البته این امر پیش فرض است ولی برای دادههای مثل آرایه، رشتهای، ادرس فرستاده میشود و ارسال از نوع مرجع میشود
Boxing و UnBoxing
Boxing عمل تبدیل مقدار نوع دادهای به نوع مرجع مشابه آن میباشد.
مثال:
int foo = 42;// Value type... object bar = foo;// foo is boxed to bar.
UnBoxing عمل تبدیل نوع مرجع به نوع دادهای میباشد. مثال:
int foo = 42;// Value type. object bar = foo;// foo is boxed to bar. int foo2 = (int)bar;// Unboxed back to value type.
سی شارپ به برنامه نویس با استفاده از کلمه کلیدی Struct اجازه میدهد تا انواع مقداری User-defined را ایجاد کند. از دیدگاه برنامهنویسی، آنها کلاسهای سبک وزن به نظر میرسند. برخلاف کلاسها (که بر روی heap قرار میگیرند) و شبیه به انواع اولیه استاندارد مانند انواع مقداری Structها نیز بر روی پشته قرار میگیرند. آنها همچنین میتوانند قسمتی از یک شئ باشند، یا در یک آرایه مرتب شوند، بدون حافظه غیر مستقیمی که به طور معمول برای انواع کلاس تخصیص مییابد.
ویژگیهای جدید در سی شارپ ۲٫۰
ویژگیهای جدید در سی شارپ چارچوب داتنت SDK ۲٫۰ (مطابق با سومین ویرایش استاندارد ECMA-۳۳۴):
کلاسهای partial
کلاسهای Partial اجازه اجرای کلاسها از بیش از یک سورس فایل را میدهند. این امر اجازه میدهد تا کلاسهای بسیار بزرگ را قطعه قطعه کنیم و همچنین برای زمانی که برخی قسمتهای یک کلاس به طور خودکار تولید میشوند مفید است.
file1.cs:
public partial class MyClass { public MyClass() { // implementation } }
file2.cs:
public partial class MyClass { public void SomeMethod() { // implementation } }
Genericها
genericها یا نوعهای پارامتری شده یا چندریختیهای پارامتری یک ویژگی جدید چارچوب داتنت ۲٫۰ است که به وسیله سی شارپ پشتیبانی میشود. برخلاف Templateهای سی پلاس پلاس، در این انواع به جای اینکه نمونه سازی توسط کامپایلر انجام شود، در زمان اجرا صورت میگیرد، بنابراین میتوانند چند زبانه باشند در حالی که ++C نمیتواند. آنها دارای ویژگیهایی هستند که به طور مستقیم توسطTemplateهای C++ پشتیبانی نمیشوند مانند نوع محدودیتها در پارامترهای Generic با استفاده از رابطها(Interface). سی شارپ از پارامترهایهای Generic بدون نوع پشتیبانی نمیکند. بر خلاف genericهای جاوا،genericهای دات نت برای پارامتری کردن انواع دادهای در اشیا ماشین مجازی CLI، از مفاهیم شیءگرایی استفاده میکنند که اجازه بهینهسازی و حفاظت انواع اطلاعات را میدهد.
کلاسهای static
کلاسها به صورت Static قابل تعریف نیستند مگر اینکه تمام اعضای آنها Static باشند؛ که این امر بسیار شبیه به مفهوم مدل در زبانهای رویهای است. (زبان رویهای: یک زبان برنامهنویسی که در آن عنصر اصلی برنامهنویسی یک زیربرنامهاست. مانند زبانهای C، پاسکال و…)
پرونده:Imag|بندانگشتی|وسط|slam
=== یک شکل جدید از تکرار کننده با استفاده از سازنده توابع === یک شکل جدید از iterator(تکرار کننده)، با استفاده از ساختار yield return بسیار شبیه به yield زبان Python.
// Method that takes an iterable input (possibly an array) and returns all even numbers. public static IEnumerable<int> GetEven(IEnumerable<int> numbers) { foreach (int i in numbers) { if (i % 2 == 0) yield return i; } }
Delegateهای ناشناس
Delegate یک شی میباشد که حاوی یک یا چند اشاره گر به توابع میباشد؛ که با Invoke کردن آن تمامی توابع اشاره شده داخل آن اجرا میشوند.
Delegateهای ناشناس که عملکردهای محدودی را در سی شارپ به وجود میآورند. کد کنار بدنه Deletage ناشناس، دسترسی کامل برای خواندن یا نوشتن در متغیرهای عمومی، پارامترهای توابع و اعضای کلاسهای دارای محدوده Deletage را دارد ولی پارامترهای out و ref را پشتیبانی نمیکند. برای مثال:
int SumOfArrayElements(int[] array) { int sum = 0; Array.ForEach( array, delegate(int x) { sum += x; } ); return sum; }
Delegate covariance and contravariance
تبدیل گروههای متد به نوع Deletage در برگشت دارای covariant و در انواع پارامترها دارای contravariant هستند.
اکسسورهای یک خاصیت(get و set) میتوانند دارای سطح دسترسی متفاوتی باشند
مثال:
string status = string.Empty; public string Status { get { return status; }// anyone can get value of this property, protected set { status = value; }// but only derived classes can change it }
نکته مهم: سطح دسترسی خاصیت نمیتواند بالاتر از سطح دسترسی اکسسورها باشد. به عنوان مثال private بودن خاصیت و public بودن اکسسور باعث بروز خطا میشود.
نوع داده Nullable
نوع داده Nullable (که با یک علامت سوال قابل تشخیص است: int? i = null;)اجازه تخصیص مقدار null را برای انواع دادهای میدهد. این امر باعث بهبودی فعل و انفعال با پایگاه داده SQL میشود. در این حالت نوع ستونی INTEGER NULL در SQL به طور مستقیم به int? در سی شارپ تبدیل میشود.
دادههای Nullable در آخرین لحظات آگوست ۲۰۰۵ اضافه شدند چند هفته مانده به اتمام کار اداری و برای بهبود زبان. متغیر Null در حقیقت خالی نیست، بلکه نمونهای است از struct Nullable<T> با ویژگی HasValue مساوی false. وقتی در برنامه قرار میگیرد، خود به خود نمونه خالی در آن قرار میگیرد، نه مقدار خود آن، در نتیجه اشاره گر مقصد همیشه غیر Null میباشد، حتی برای مقادیر Null. کد زیر نضص بالا را مشخص میکند:
int? i = null; object o = i; if (o == null) Console.WriteLine(«Correct behaviour - runtime version from September 2005 or later»); else Console.WriteLine(«Incorrect behaviour - pre-release runtime (from before September 2005)»);
وقتی درون شی ای کپی میشود، نمونه Nullable به صورت تشریفاتی در آن قرار میگیرد و در نتیجه مقادیر و منابع Null با هم برابر میشوند. در گذشته این خاصیت دارای مجادله بود تا زمانی که علاوه بر چارچوب داتنت ۲، به هسته CLR نیز مجهز شد و همه تکنولوژیها نظیر سی شارپ، ویژوال بیسیک، مایکروسافت اسکیوال سرور ۲۰۰۵ و مایکروسافت ویژوال استودیو ۲۰۰۵ را شامل شد.
Coalesce Operator
مقدار اولین عملوندی که null نباشد را برمیگرداند. (یا null، برای زمانی که تمام عملوندها null باشند)
object nullObj = null; object obj = new Object(); return nullObj ?? obj;// returns obj
کاربرد اصلی این عملگر در قرار دادن یک مقدار nullable در یک مقدار non-nullable با استفاده از یک دستورالعمل سادهاست.
int? i = null; int j = i ?? 0; /* Unless i is null, initialize j to i. Else (if i is null), initialize j to 0. */
ویژگیهای جدید در سی شارپ ۳٫۰
این ورژن در تاریخ ۱۹ نوامبر سال ۲۰۰۷ به عنوان بخشی از چارچوب داتنت ۳٫۵ عرضه شد؛ که شامل ویژگیهای جدید الهام شده از زبانهای برنامهنویسی اصلی (Functional) مانند Haskell و ML، و الگوی LINQ برای CLR است. در حال حاضر توسط هیچ موسسه استانداردسازی تائید نشدهاست.
معرفی لینک
لینک (به انگلیسی: Language Integrated Query)(مخفف انگلیسی: LINQ) یک زبان پرس و جوی قابل انعطاف و همه منظوره برای بسیاری از انواع منبع دادهها است (مثل انتخاب اشیا شناور، سندهای XML، بانکهای اطلاعاتی و…) که در ویژگیهای سی شارپ ۳ جمع شدهاند. سینتکس زبان به زحمت از SQL گرفته شدهاست، برای مثال:
int[] array = { 1, 5, 2, 10, 7 }; // Select squares of all odd numbers in the array sorted in descending order IEnumerable<int> query = from x in array where x % 2 == 1 orderby x descending select x * x;
مقدار دهی به اشیا
Customer c = new Customer(); c.Name = "James";
عبارت بالا میتواند به صورت زیر نوشته شود:
Customer c = new Customer { Name="James" };
مقدار دهی Collection
MyList list = new MyList(); list.Add(1); list.Add(2);
عبارت بالا میتواند به صورت زیر نوشته شود:
MyList list = new MyList { 1, 2 };
فرض کنید که اجزای MyList و System.Collections.IEnumerable دارای متد عمومی Add هستند.
انواع دادهای بی نام
var x = new { FirstName="James", LastName="Frank" };
سی شارپ ۲٫۰ توابع بی نام را معرفی کرد. سی شارپ ۳٫۰ هم انواع بی نام را معرفی میکند. با استفاده از این ویژگی برنامه نویسان قادر خواهند بود به صورت Inline انواع دلخواه خود را ایجاد کنند. به نمونه زیر توجه کنید:
static void Main(string[] args) { var anonymousType = new { Name = string.Empty, Age = 0 }; }
کد ارائه شده، یک نوع بی نام را تعریف میکند که از طریق متغیر ضمنی محلی به نام anonymousType در اختیار قرار میگیرد.
چرا Anonymous types؟ انواع بی نام بهترین گزینه برای تولید Entity Typeها میباشند. همانطور که گفته شد Entity Typeها فقط حاوی دادهها هستند؛ بنابراین به بهترین نحو میتوان دادههای دریافت شده از کاربر را در انواع بی نام بسته بندی کرد.
نتیجه نوع متغیر محلی
var x = new Dictionary<string, List<float>>();
کد بالا با کد زیر قابل تعویض میباشد:
Dictionary<string, List<float>> x = new Dictionary<string, List<float>>();
این ویژگی تنها یک ntactic sugarراحت برای کوتاه تر بیان کردن متغیرهای محلی نمیباشد، بلکه برای تعریف متغیرهای بی نام لازم نیز است.
عبارات لامبدا
عبارات لامبدا یک راه کوتاه برای نوشتن مقادیر توابع بی نام کلاس اول را فراهم میکنند. دو مثال زیر را در نظر بگیرید:
listOfFoo.Where(delegate(Foo x) { return x.Size> 10; })
listOfFoo.Where(x => x.Size> 10);
در مثالهای فوق، عبارات لامبدا صرفاً یک نوع سینتکس برای delegateهای بی نام با مقادیر دارای بازگشت هستند. هر چند با توجه به نوع متن استفاده میشوند، کامپایلر سی شارپ میتواند لامبداها را به ASTها نیز تبدیل کند تا بعداً در زمان اجرا نیز بتوانند پردازش شوند. در مثال فوق، اگر listOfFoo یک مجموعه ساده داخل حافظه نباشد، ولی یک پوشه در اطراف جدول بانک اطلاعاتی میباشد. این تکنیک میتواند برای بهینه کردن اجرا، برای ترجمه بدنه لامبدا به عبارت معادل آن در SQL استفاده شود. در هر یک از دو راه فوق، خود عبارت لامبدا دقیقاً شبیه کد به نظر میرسد، بنابراین روش استفاده در زمان اجرا، برای کاربر ناپیدا میباشد.
یکی از ویژگیهایی که سی شارپ ۲٫۰ ارائه کرد، توانایی تعریف توابع به صورت Inline بود که این ویژگی با عنوان توابع بی نام (anonymous methods) شناخته میشود. توابع بی نام در پارهای مواقع بسیار مفیدند. اما نحو(syntax) به کارگیری آنها دشوار میباشد. عبارات لامبدا ویژگی توابع بی نام را دارند اما با نحو سادهتری در سی شارپ ۳٫۰ معرفی شدهاند. به نمونه زیر توجه کنید:
static void Main(string[] args) { (int x) => x + 1;// explicitly typed parameter (y, z) => y * z;// implicitly typed parameter }
تعریف عبارات لامبدا از نحو (syntax) خاصی پیرو میکند. همانطور که در کد بالا مشاهده میکنید، پارامترهای تابع هم به صورت صریح و هم به صورت ضمنی قابل بیان اند. کلمه return به صورت ضمنی حذف شدهاست. تابع معادل عبارت لامبدای اول به صورت زیر است:
int Fn(int x) { return x+1; }
لیست پارامترها و بدنه عبارت لامبدا توسط => از هم جدا میشوند. در صورتی که تعریف عبارت لامبدا بیشتر از یک خط کد باشد میتوان بدنه آن را با استفاده از {} نشان داد.
static void Main(string[] args) { (int x) => { x + 1; return x * x; }; }
خواص خودکار
کامپایلر به طور خودکار یک متغیر نمونه خصوصی و قرار دهنده و قرار گیرنده مناسب تولید میکند، مانند:
public string Name { get; private set; }
توابع بسط داده شده
توابع بسط داده شده حالتی از سینتکس Suger هستند که امکان اضافه کردن متد جدید به کلاس موجود را بیرون از حوزه تعریف آن فراهم میکنند. در این مثال، تابع بسط داده شده یک تابع ایستا است که قابل فراخوانی توسط تابع مشابه میباشد. گیرنده فراخوانی مقید به اولین پارامتر تابع تحت عنوان this میباشد:
public static class StringExtensions { public static string Left(this string s, int n) { return s.Substring(0, n); } } string s = "foo"; s.Left(3);// same as StringExtensions.Left(s, 3);
زبان سی شارپ کلمه کلیدی sealed را برای این منظور ارائه کرد که امکان ارث بری از یک کلاس را صلب کند. یعنی با اضافه شدن این کلمه کلیدی به ابتدای تعریف کلاس، امکان ارث بری از آن غیر ممکن میشود. سی شارپ ۳٫۰ ویژگی جدیدی را در اختیار برنامه نویسان قرار میدهد به این صورت که میتوان هر نوع کلاسی حتی کلاسهای مهر شده با Sealed را با استفاده از Extension methodsبسط داد.
توابع جزئی
توابع جزئی به تولید کنندههای کد اجازه تولید اعلان توابع به صورت نقاط گسترش یافتهای که تنها شامل کدهای اصلی هستند را میدهد، در صورتی که یک نفر آن را در قسمتی از کلاسی دیگر اجرا کند.
متغیرهای ضمنی محلی
سی شارپ ۳٫۰ کلمه کلیدی جدید var را معرفی میکند که به کمک آن برنامه نویسان قادر خواهند بود متغیرهای محلی خود را بدون ذکر صریح نوع آنها، تعریف کنند.
namespace CS3_Test { class Program { static void Main(string[] args) { var string_value = "Hello C# 3.0"; var int_value = 3; } } }
یکی از ویژگیهای اصلی زبان سی شارپ،Strong Type بودن آن است. Strong Type بودن زبان به این معناست که با اعلان یک متغیر، نوع آن صریحاً باید توسط برنامه نویس مشخص شود. آیا اضافه شدن این ویژگی جدید، منافاتی با Strong Type بودن این زبان دارد؟ در پاسخ باید گفت که تعریف متغیرهای محلی به صورت ضمنی با استفاده از کلمه کلیدی var هیچ گونه منافاتی با Strong Type بودن سی شارپ ندارد. چون برنامه نویس میبایست نوع متغیر را به هنگام اعلان آن صریحاً مشخص کند. نوع متغیر پس از اولین اعلان تا اتمام حوزه تعریف آن تغییر نخواهد کرد و هر گونه تلاش برای تغییر نوع با خطا مواجه خواهد شد؛ بنابراین دو اعلان زیر نامعبر هستند:
namespace CS3_Test { class Program { static void Main(string[] args) { var string_value;// Error: Implicitly typed locals must be inintialized var int_value = null; /* Error: Cannot assign '<null>' to an implicitly typed local */ } } }
استفاده از var تنها در تعریف متغیرهای محلی امکانپذیر است. در اعلان متغیرها به صورت سراسری، پارامترهای توابع و مقادیر بازگشتی نمیتوان از var استفاده کرد. چرا var؟ این ویژگی آزادی عملی بیشتری برای کار با متغیرهای محلی در اختیار برنامه نویس قرار میدهد. سناریویی را در نظر بیگیرید که یک تابع تحت شرایطی، مقادیر از انواع مختلف را برگرداند. در این صورت بدون درگیر شدن با casting و تبدیل نوع میتوان با تعریف متغیر ضمنی محلی هر نوعی را که تابع برمیگرداند، در اختیار داشت.
سازندههای پیشرفته
ماهیت تمامی برنامههای امروزی به گونهایست که با حجم عظیمی از دادهها سرو کار دارند. برای مدیریت دادهها، نیاز به کلاسهاییست که در مهندسی نرمافزار آنها را Entity Types مینامیم. این کلاسها به عنوان بستههایی از دادهها محسوب میشوند. معضل فعلی موجود در رابطه با Entity Typeها تعدد سازندههای آنها میباشد و ممکن است شما نیز با این مشکل برخورد کرده باشید. به این صورت که در سناریوهای مختلف، برنامهنویسان مجبور هستند سازنده یک کلاس را به چند شکل سربارگذاری کنند. سی شارپ ۳٫۰ راه چارهای فوقالعاده برای این مشکل ارائه میدهد. Object initializer حالت پیشرفتهای از سازنده میباشد.
class Person { private string firstname; public string FirstName { get { return firstname; } set { firstname = value; } } private string lastname; public string LastName { get { return lastname; } set { lastname = value; } } private int age; public int Age { get { return age; } set { age = value; } } }
این کلاس شامل سه متغیر بوده و برای هر متغیر خاصیتی تعریف شدهاست. اینک این سوالات مطرح میشوند: سازنده این کلاس را به چند شکل باید سربارگذاری کرد؟ سازندهای که هر سه متغیر را مقداردهی کند؟ شاید در مواردی هر سه متغیر در دست نباشد در این صورت چه سازندهای باید فراخوانی شود؟ سی شارپ ۳٫۰ راه حل زیر را ارائه میدهد. فرض کنید بخوانیم نمونهای ازکلاس Person را ایجاد کنیم. همانطور که مشاهده میکنید، در سی شارپ ۳٫۰ به هنگام نمونه سازی، این امکان در اختیار برنامه نویس قرار میگیرد که هر یک از خصیصههای موجود در کلاس را به دلخواه و بنا به نیاز مقدار دهی کند به صورت زیر:
Person person = new Person ( Age = 21, FirstName = "James", LastName = "Frank");
عبارات جستجو (Query Expression)
تیم طراح سی شارپ ویژگی فوقالعادهای را به آن اضافه کرد که برنامه نویسان را قادر میسازد نحو (Syntax) زبانهای پرس و جو مانند SQL و XQuery را با استفاده از این زبان پیادهسازی کنند. این ویژگی با نام اختصاری LINQ شناخته میشود و دارای انواع زیر است:
- LINQ-to-Objects – talks to in-memory objects
- LINQ-to-SQL – talks to SQL Server databases
- LINQ-to-XML – talks to hierarchical data represented in XML
- LINQ-to-DataSets – talks to DataSet objects and underlying DataTables with their relationships
- LINQ-to-Entities – talks to “entities”، part of ADO.NET ۳٫۰
نمونهای از کاربرد LINQ به صورت زیر است:
static void Main(string[] args) { var int_array = new int[] { 1, 2, 7, 9, 12 }; var selective_array = from c in int_array where c> 5 select c; foreach (var selected in selective_array) { Console.WriteLine(selected); } }
توضیح: در مثال بالا ابتدا یک آرایهٔ int با مقداردهی اولیه تعریف شدهاست. سپس با استفاده از دستورها) LINQ که جز کلمات کلیدی سی شارپ محسوب میشوند)، آرایهای با اعضای بزرگتر از ۵ انتخاب و در متغیر ضمنی محلی selective_array ذخیره میشود. در نهایت اعضای selective_array به صورت ۷ و ۹ و ۱۲ خواهد بود. در توضیح این ویژگی جدید به همین یک مثال بسنده میکنیم چون بیان تمامی جنبههای LINQ خود نیازمند نگارش مقالهای مفصل میباشد.
آرایههای نوع ضمنی
آرایهها را نیز میتوان با استفاده از کلمه کلیدی var تعریف کرد.
static void Main(string[] args) { var a = new[] { 1, 10, 100, 1000 };// int[] var b = new[] { 1, "one", 2 };// Error }
پیش پردازنده
ویژگی «دستورها پیش پردازنده» سی شارپ(اگرچه آنها به واقع یک پیش پردازنده نیستند) مبنی بر دستورها پیش پردازنده C است که به برنامه نویس اجازه تعریف سمبلهایی را میدهند. برخی از این دستورها عبارتند از: #if، #region، #define. راهنماهایی نظیر #region تذکراتی به ویرایشگرها برای code folding میدهند.
توضیحات کد
توضیحات تک خط با استفاده از دو اسلش تعریف میشوند(//) و توضیحات چند خطی با /* شروع و به */ ختم میشوند.
public class Foo { // a comment public static void Bar(int firstParam) {}//Also a comment } public class FooBar { /* a comment */ public static void BarFoo(int firstParam) {} /* Also a comment */
توضیحات چند خطی هم چنین میتوانند با /* شروع و با */ تمام شوند.
public class Foo { /* A Multi-Line comment */ public static void Bar(int firstParam) {} }
سامانه مستندسازی XML
سامانه مستندسازی سی شارپ بسیار شبیه به جاوا است، اما مبنی بر XML. دو شیوه مستندسازی در حال حاضر به وسیله کامپایلر سی شارپ پشتیبانی میشود.
توضیحات تک خطی، که معمولاً در تولید کننده کد Visual Studioپیدا میشوند، با استفاده از/// شروع میشوند.
public class Foo { /// <summary>A summary of the method.</summary> /// <param name="firstParam">A description of the parameter.</param> /// <remarks>Remarks about the method.</remarks> public static void Bar(int firstParam) {} }
توضیحات چند خطی، که در نسخه ۱٫۰ تعریف شدند، اما در نسخه ۱٫۱ پشتیبانی از آنها وجود نداشت با /* شروع و به */ ختم میشوند:
public class Foo { /** <summary>A summary of the method.</summary> * <param name="firstParam">A description of the parameter.</param> * <remarks>Remarks about the method.</remarks> */ public static void Bar(int firstParam) {} }
نتکه:در اینجا یک ملاک سخت در مورد استفاده از فضاهای خالی در سندهای XML هنگام استفاده از /**وجود دارد:
/**
* <summary>
* A summary of the method.</summary>*/
نوع دیگری از کد بالا ارائه خواهد شد:
/**
* <summary>
A summary of the method.</summary>*/
سینتکس سندسازی توضیحات XML در یک ضمیمه بی قاعده از استاندارد ECMA از سی شارپ وجود دارد. یک استاندارد مشابه قوانینی برای پردازش توضیحات و تبدیل آنها به متون Plain در XML را با کمک قوانین CLI فراهم میکند. این به هر IDE در سی شارپ و دیگر ابزار گسترش دهنده امکان پیدا کردن هر نمادی را در کدها میدهد.
(CLR(Common Language Runtime
بخش مرکزی چارچوب داتنت، محیط اجرایی Runtime میباشد که اصطلاحاً به آن CLR یا .NET Runtime میگویند. کدهایی که تحت کنترل CLR اجرا میشوند اغلب به عنوان کدهای مدیریت شده نامیده میشوند.
اگر چه، پیش از این که کدها (همه زبانهای چارچوب داتنت) به وسیله CLR اجرا شوند، بایستی مورد کامپایل قرار گیرند. در چارچوب داتنت عمل کامپایل در دو مرحله صورت میگیرد:
- کامپایل سورس کد به MSIL.
- کامپایل MSIL به کد مختص پلتفرم به وسیله CLR
یک نکته قابل توجه، اشتراک زبان میانی مایکروسافت با کد بایت جاوا(Bytecode)است. ایدة این اشتراک از آنجا سرچشمه گرفت که چون Bytecode یک زیان سطح پایین با یک دستور زبان ساده میباشد (که به جای متن مبتنی بر کدهای عددی است)، میتواند به سرعت به کدهای بومی(Native) ترجمه شود.
برخی ویژگیهای MSIL
- شیءگرایی و بکارگیری واسطها
- تمایز فراوان بین انواع مقداری و ارجاعی
- تعیین Strong Type (این نوع داده دیگر معتبر نیست)
- مدیریت خطا از طریق به کارگیری Exception
- بکارگیری صفات
اشکالات
پلتفرم
منبع چارچوب داتنت مایکروسافت برای اجرا فقط ویندوز است. پیادهسازیهای دیگری برای اجرای برنامههای سی شارپ در ویندوز، لینوکس،BSD یا Mac OS X وجود دارند اما هنوز کامل نیستند: Mono و DotGNU در نوامبر سال ۲۰۰۲ توسط مایکروسافت(نسخه ۱٫۰) برای پیادهسازی CLI برای کار در Free BSD و Mac OS X ۱۰٫۲ ارائه شد، اما نسخههای بعدی آنها فقط قابل اجرا بر روی ویندوز بود.
پیشرفت در آینده
نسخه بعدی این زبان، سی شارپ ۴ است که از اکتبر سال ۲۰۰۸ در حال ساخته شدن است. ماکروسافت لیستی از ویژگیهای جدید سی شارپ ۴ را در کنفرانس توسعه دهندگان حرفهای اعلام کردهاست. تمرکز اصلی در ورژن بعدی روی قابلیت هماهنگی فریم ورکها و نوع زبانهایی است که کامال پویا یا قیمتی پویا هستند، مانند dynamic language runtime و COM. ویژگیهای زیر تا کنون اعلام شدهاند:
پارامترهای نوع generic از نوع Covariant و contravariant
پارامترهای واسطهای generic و deletageها میتوانند با استفاده از کلمات out و in از دو نوع Covariant و contravariant باشند. این تعیین نوعها بعداً برای تبدیل انواع به یکدیگر، چه از نوع صریح یا مجازی و چه از نوع compile-time یا run-time به کار میرود. به عنوان مثال، واسط IEnumerable<T> در زیر دوباره تعریف شدهاست:
interface IEnumerable<out T> { IEnumerator<T> GetEnumerator(); }
بنابراین، هر کلاس مشتق شدهای که از IEnumerable<Derived> استفاه کرده باشد، با تمام کلاسهای پایه که IEnumerable<Base> را دارند سازگار است. به عنوان تمرین، کد زیر نوشته شدهاست:
void PrintAll(IEnumerable<object> objects) { foreach (object o in objects) { Console.WriteLine(o); } } IEnumerable<string> strings = new List<string>(); PrintAll(strings);// IEnumerable<string> is implicitly converted to IEnumerable<object>
برای contravariance، رابط IComparer<T> به صورت زیر دوباره تعریف شدهاست:
public interface IComparer<in T> { int Compare(T x, T y); }
بنابراین، هر کلاسی که IComparer<Base> را برای یک کلاس پایه بیان میکند، با IComparer<Derived> در تمام واسطها و کلاسهایی که از آن کلاس پایه مشتق شدهاند، سازگار است. این امر نوشتن کد زیر را میسر میسازد:
IComparer<object> objectComparer = GetComparer(); IComparer<string> stringComparer = objectComparer;
جستجوی عضو پویا
در سامانه انواع دادههای سی شارپ یک نوع جدید با نام شبه-نوع معرفی شدهاست که مانند System.Object رفتار میکند، ولی در ادامه، هر دسترسی به اعضا یا برنامههایی که از این نوع استفاده میکنند، بدون چک شدن نوع دادههایشان اجازه کار دارند و تجزیه آنها تا زمان اجرا به تعویق میافتد. به عنوان مثال:
// Returns the value of Length property or field of any object int GetLength(dynamic obj) { return obj.Length; } GetLength(«Hello, world»);// a string has a Length property, GetLength(new int[] { 1, 2, 3 });// and so does an array, GetLength(42);// but not an integer - an exception will be thrown here at run-time
صدا زده شدنهای متد پویا، مانند پارامترهای صریح یا مجازی با مقدار نوع dynamic راهاندازی میشوند. به عنوان مثال:
void Print(dynamic obj) { Console.WriteLine(obj);// which overload of WriteLine() to call is decided at run-time } Print(123);// ends up calling WriteLine(int) Print("abc");// ends up calling WriteLine(string)
جستجوی پویا تحت سه مکانیزم مشخص اجرا میشود: COM IDispatch برای اشیا COM، رابط IDynamicObject DLR برای اشیا دارای این واسط و Reflection برای بقیه اشیا؛ بنابراین هر کلاس سی شارپ میتواند صدا زده شدنهای پویای خود را با اجرای IDynamicObject در نمونههای خود جدا کند. در مورد متدهای پویا و مشخص کننده صدا زدنها، تجزیه و تحلیل اضافه بار مطابق انواع اصلی که به عنوان آرگومانها هستند، در زمان اجرا اتفاق میافتد، در غیر این صورت بر اساس قوانین تجزیه و تحلیل اضافه بار سی شارپ عمل خواهد شد. به علاوه، در مواردی که در صدا زدن پویا، گیرنده خودش پویا نیست، تجزیه و اضافه بار زمان اجرا تنها به متدهایی که در زمان کامپایل به صورت گیرنده ظاهر شدهاند، رسیدگی میکند. به عنوان مثال:
class Base { void Foo(double x); } class Derived: Base { void Foo(int x); } dynamic x = 123; Base b = new Derived(); b.Foo(x);// picks Base.Foo(double) because b is of type Base, and Derived.Foo(int) is not exposed dynamic b1 = b; b1.Foo(x);// picks Derived.Foo(int)
هر مقداری که توسط دستیابی به عضو پویا برگردانده شده باشد، خودش از نوع پویا است. مقادیر نوع پویا به سایر نوعها و از سایر نوع عا قابل تبدیل هستند. در نمونه کد بالا، این امر به تابع GetLength اجازه با مقدار بازگردانده شده از Length بدون هیچ صریحی به عنوان integer استفاده کند. در زمان اجرا، مقدار واقعی به نوع خواسته شده تبدیل میشود.
کلمه کلیدی اختیاری ref
در حال حاضر کلمه کلیدی ref برای متدهای صدا زننده اختیاری است. کد زیر را در نظر بگیرید:
void Increment(ref int x) { ++x; } int x = 0; Increment(ref x);
به صورت زیر هم میتواند نوشته شود:
void Increment(ref int x) { ++x; } int x = 0; Increment(x);
آرگومنتهای نام گذاری شده و پارامترهای اختیاری
در سی شارپ ۴ پارامترهای اختیاری ای با مقادیر پیش فرض موجود در ++C معرفی میشوند. به عنوان مثال:
void Increment(ref int x, int dx = 1) { x += dx; } int x = 0; Increment(ref x);// dx takes the default value of 1 Increment(x, 2);// dx takes the value 2
به علاوه، برای کامل کردن پارامترهای اختیاری، میتوانید صریحاً نام پارامترها را در صدازدنهای متدها تعیین کنید. این کار به شما اجازه تصویب کردن انتخابی برای هر زیر مجموعه اختیاری از پارامترهای متد را میدهد. تنها محدودیت موجود این است که پارامترهای نام دار باید بعد از پارامترهای بدون نام بیایند. نام پارامترها میتوانند برای هر دو نوع پارامترهای اختیاری و ضروری تعیین شوند و میتوانند برای بهبود خوانایی و فراخوانی دوباره آرگومانها مفید باشند. به عنوان مثال:
Stream OpenFile(string name, FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read) { ... } OpenFile("file.txt");// use default values for both "mode" and "access" OpenFile("file.txt", mode: FileMode.Create);// use default value for "access" OpenFile("file.txt", access: FileAccess.Read);// use default value for "mode" OpenFile(name: "file.txt", access: FileAccess.Read, mode: FileMode.Create);// name all parameters for extra readability, and use order different from method declaration
پارامترهای اختیاری inter-operating را با COMراحت تر میکنند. در گذشته، سی شارپ مجبور بود تمام پارامترهای متد سازنده COM را پشت سر بگذازد، حتی آنهایی را که اختیاری بودند؛ به عنوان مثال:
object fileName = "Test.docx"; object missing = System.Reflection.Missing.Value; doc.SaveAs(ref fileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
با پشتیبانی از پارامترهای اختیاری، کد بالا میتواند به صورت زیر خلاصه شود:
doc.SaveAs("Test.docx");
کتابخانهها
جزئیات مشخصات سی شارپ، حداقل تعداد نوعها و کتابخانههای کلاس است که کامپایلر نیاز به وجود آنها دارد. عملاً، اغلب سی شارپ توسط بیشترین استفاده از CLI را میکند، که استاندارد شده ECMA-۳۳۵ است.
مثال Hello world
در زیر یک مثال ساده از برنامه سی شارپ آمدهاست، نسخهای از مثال کلاسیک Hello World:
class ExampleClass { static void Main() { System.Console.WriteLine("Hello, world!"); } }
نتیجه، چاپ شدن متن زیر د خروجی است:
Hello, world!
هر خط هدفی دارد:
class ExampleClass
در بالا، تعریف کلاس آمدهاست. هر چیزی که در بین در علامت پرانتز باشد،ExampleClass را توصیف میکند:
static void Main()
این یک تابه عضو کلاس را در زمان شروع اجرای برنامه اعلان میکند. دات نت در زمان اجرا، تابع Main را صدا میزند (نکته: Main ممکن است از هر جای دیگری نیز صدا زده شود، مثلاً توسط تابع ExampleClass و با کد ()Main). کلمه کلیدی static تابع را بدون داشتن نمونهای از ExampleClass قابل دسترس میکند. هر تابع Main در هر کنسولی باید به صورت static تعریف شود. در غیر این صورت برنامه به یک نمونه نیاز خواهد داشت و هر نمونه به یک برنامه نیاز دارد. برای اجتناب از این وابستگی دایرهای تجزیه ناپذیر، کامپایلرهای سی شارپ در صورت Static نبودن تابع Main، یک خطا اعلام میکنند. کلمه کلیدی void نشان دهنده این است که تابع Main هیچ مقداری را بر نمیگرداند.
Console.WriteLine("Hello, world!");
خط بالا، خروجی را مینویسد. در فضای اسم System، Console یک کلاس استاتیک است که یک میانجی بین ورودی، خروجی و خطای کنسول میباشد. برنامهای که متدWriteLine را از کنسول صدا میزند، خروجی رشته «Hello، world!» را در خروجی نمایش میدهد.
استانداردسازی
در آگوست سال ۲۰۰۰، شرکت مایکروسافت، و Hewlett-Packard و شرکت اینتل به عنوان پشتیبان مشخصات سی شارپ را مانند CLI به سازمان استانداردسازی ECMA ارائه کردند. در دسامبر سال ۲۰۰۱، این سازمان، ECMA-۳۳۴ را با عنوان مشخصات زبان سی شارپ منتشر کرد. سی شارپ در سال ۲۰۰۳ به عنوان یک استاندارد ISO به ثبت رسید(ISO/IEC ۲۳۲۷۰). در سال ۲۰۰۲، ECMA دومین ویرایش از خصوصیات زبان سی شارپ را پذیرفت.
در ژوئن سال ۲۰۰۵، ECMA سومین ویرایش را با اضافه کردن مواردی همچون کلاسهای partial، متدهای ناشناس، انواع nullable و Genericها منتشر کرد. در ژوئیه ۲۰۰۵، ECMA استانداردها و TRها را همراه با پردازش Fast-Track اخیر به ISO/IEC JTC پیشنهاد کرد. این روند معمولاً ۶ تا ۹ ماه زمان میبرد. آخرین ویرایش این زبان در ۱۵ آگوست سال ۲۰۱۲ در قالب Framework ۴٫۵ارائه گردید
کارائی
با توجه به توابع موجود در چارچوب داتنت امکان استفاده از این توابع وجود دارد که میتوان گفت برای هر کاری شرکت ماکروسافت تابعی پیش بینی کرده؛ که این امکان را ایجاد میکند که به فایل اصلی پروژه هیچ فایل کتابخانی را اضافه نکنید (هم به صورت دستی یا خود کمپایلر). این موضوع خود باعث ایجاد فایلهای خروجی با حجم بسیار کم میشود. این موضوع در بسیاری از موارد بسیار اهمیت دارد. برنامههای سی شارپ، همچون تمام برنامههای نوشته شده در چارچوب داتنت و سایر محیطهای ماشینی مجازی مانند جاوا، نیازمند منابع سامانه و حافظه بیشتری نسبت به برنامههای نوشته شده با سایر زبانها مانند سی پلاس پلاس است و هم چنین سرعت کمتری نیز دارد. هر چند تعریف زبان سی شارپ و CLI تحت استانداردهای ISO و ECMA استاندارد شدهاند،CLI تنها قسمتی از Base Class Library (BCL) ماکروسافت میباشد که شامل کلاسهای غیر استاندارد استفاده شده در برنامههای سی شارپ نیز میشود. از این گذشته، بعضی از قسمتهای BCL تحت حق امتیاز ماکروسافت هستند که ممکن است پیادهسازی کامل framework را مختل کند، زیرا تنها بخشهای استاندارد دارای حق محافظت RAND در برابر مدعیان را دارند.
پیادهسازیها
متداولترین کامپایلر سی شارپ، Microsoft Visual C# میباشد.
- کامپایلرهای سی شارپ
- پروژه Microsoft Rotor (در حال حاضر به عنوان Shared Source Common Language Infrastructure شناخته میشود) (ثبت شده فقط برای استفاده آموزشی و تحقیقی) یک پیادهسازی منبع اشتراکی از CLR Runtime را فراهم میآورد و یک کامپایلر سی شارپ، و یک زیرمجموعه از کتابخانه]] CLI Framework مورد نیاز.
- پروژه Mono یک اوپن سورس از کامپایلر سی شارپ است، یک پیادهسازی اوپن سورس کامل از CLI شامل کتابخانههای Framework مورد نیاز که در ECMA ظاهر شدهاند، و یک پیادهسازی کامل نزدیک به بقیه کتابخانههای اختصاصی کلاس چارچوب داتنت مایکروسافت.
- پروژه DotGNU نیز یک اوپن سورس از کامپایلر سی شارپ است، که پیادهسازی آن بسیار نزدیک به Common Language Infrastructure میباشد و کتابخانههای framework مورد نیاز موجود در ECMA و زیر مجموعهای از کلاسهای کتابخانهای شخصی ماکروسافت در دات نت و دات نت ۲ را در بر دارد.
کاملاً شبیه به پروژه Mono.
نام زبان
اسم سی شارپ از علامت موسیقی شارپ گرفته شدهاست که در موسیقی بیان گر این است که متن نوشته شده باید نیم قدم از خط بالاتر باشد. مطابق با ECMA-۳۳۴، بخش ۶، مخففها و اختصارها، نام زبان به صورت «#C» نوشته میشود(«کلمه لاتین C (U+۰۰۴۳) به همراه علامت عددی #(U+۰۰۲۳)») که به صورت «سی شارپ» تلفظ میشود. علامت «#» نباید با علامت شارپ در موسیقی(♯، U+۲۶۶F) که در یک صفحه کلید استاندارد وجود ندارد اشتباه گرفته شود. پسوند شارپ، توسط بسیاری دیگر از زبانهای دات نت مانند #J، #A و #F نیز به کار رفتهاست. پیادهسازی اولیه از زبان ایفل تحت دات نت نیز #Eiffel نام داشت که الان زبان ایفل را به طور کامل پشتیبانی میکند. هم چنین این پسوند بعضی وقتها در کتابخانهها نیز به کار میرود، مانند #Gtk، #Cocoa و #Qt.