ویژگیهای جدید در سی شارپ ۳٫۰
این ورژن از سی شارپ در تاریخ ۱۹ نوامبر سال ۲۰۰۷ به عنوان بخشی از چارچوب داتنت ۳٫۵ عرضه شد؛ که شامل ویژگیهای جدید الهام شده از زبانهای برنامهنویسی اصلی (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 تعریف کرد.
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
سامانه مستندسازی #C بسیار شبیه به جاوا است، اما مبنی بر XML. دو شیوه مستندسازی در حال حاضر به وسیله کامپایلر #C پشتیبانی میشود.
توضیحات تک خطی، که معمولاً در تولیدکننده کد 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
- بکارگیری صفات
آشنایی با #C قسمت 1
آشنایی با #C قسمت 2
آشنایی با #C قسمت 3