• ¡Welcome to Square Theme!
  • This news are in header template.
  • Please ignore this message.
مهمان عزیز خوش‌آمدید. ورود عضــویت


امتیاز موضوع:
  • 8 رای - 1.75 میانگین
  • 1
  • 2
  • 3
  • 4
  • 5
Title: ويژگي هاي جديد در C# 4.0
حالت موضوعی
#1
تغییر اصلی در C# 2010 برنامهنویسی پویاست. بهطور قابل توجهی اشيا از نظر ساختار و رفتار پویا هستند، چون نمیتوان آنها را با گونههای ایستا مدیریت کرد و از طرفی کامپایلر در زمان کامپایل برنامه اطلاعات خاصی در مورد آنها در اختیار ندارد. بعضی از این موارد عبارتند از:

ü اشیایی از زبانهای برنامهنویسی پویا همانند Python و Ruby
ü اشيا COM که از طریق IDispatch به آنها دسترسی داریم
ü گونههای معمول .NET که با استفاده از انعکاس (Reflection) به آنها دسترسی پیدا کردهایم
ü اشيا با ساختار متغییر، همانند اشيا اسکریپتهای HTML DOM
ü Data Readerها و سایر اشيا پویای تعریف شده از سوی کاربر
در حالی که C# همچنان یک زبان با انواع ایستا باقی مانده، نیاز به بهبود تعامل با این نوع اشيا پویا، جزء اهداف ویرایش 2010 بوده است.
ویژگیهای جدید در C# 4.0 به چهار گروه تقسیم میشوند:

انقیاد پویا (Dynamic Binding)
مقیدسازی پویا، این امکان را به شما میدهد تا فراخوانی متدها، عملگرها و اندیکسرها، دسترسی به خصوصیات و فیلدها و همچنین احضار اشيا را به نحوی بنویسید که چک کردن گونهها به صورت ایستا در C# را دور زده و آنرا به زمان اجرا معوق کنید.

آرگومانهای اختیاری و نامگذاری شده (Named and optional argument)
با مشخص کردن مقادیر پیشفرض برای پارامترها در زمان معرفی اعضاء کلاس، شما میتوانید پارامترها را به صورت اختیاری در آورید. بنابراین زمان فراخوانی اعضاء میتوان آرگومانهای اختیاری را حذف نمود و نهایتاً هر آرگومانی را با استفاده از نام پارامتر به جای مکان پارامتر به آن عضو ارسال نمود.
ویژگیهای تعامل مخصوص COM (COM specific interop features)
انقیاد پویا و آرگومانهای اختیاری و نامگذاری شده، امکان برنامهنویسی راحتتری برای COMها را نسبت به قبل فراهم میسازند. علاوه بر این، ویژگیهای دیگری نیز در نظر گرفته شدهاند که عملیات تعامل را خصوصاً با COMها، سادهتر مینمایند.

واریانس (Variance)
قبلاً یک IEnumerable<string> با یک IEnumerable<object> متفاوت بودند. اما اکنون این دو نوع یکی هستند چون C# پذیرای نوع امن "همکاری و عدم ترکیب" (co-and Contravariance) شده است و گونههای معمول کتابخانه کلاسی پایه برای برخورداری از این ویژگی به روز شدهاند.

انقیاد پویا
انقیاد پویا یک رویکرد واحد را برای درگیر کردن موارد مختلف به صورت پویا ارائه میدهد. با انقیاد پویا، زمانی که شما شيئي را در اختیار دارید، لزومی ندارد نگران این باشید که این شئ جزء اشيا COM است یا IronPython یا HTML DOM یا یک شئ منعکس شده یا هر چیز دیگری، فقط باید عملیاتها را بر روی وی اعمال کنید و آن را به حال خود بگذارید تا در زمان اجرا مشخص شود که این عملیاتها برای آن شئ چه معنایی دارند.
این موضوع انعطافپذیری زیادی را ارائه میدهد و میتواند کدهای شما را تا حد زیادی سادهتر نماید، اما با یک مشکل همراه است و آن اینکه تعیین نوع ایستا برای این عملیاتها اعمال نمیشود. در زمان کامپایل فرض میشود که اشيا پویا همه عملیاتها را پشتیبانی میکنند، این در حالی است که اگر این موضوع درست نباشد، فقط در زمان اجرا خطایی دریافت میشود.
در بیشتر مواقع بدلیل اینکه اشيا به عنوان یکگونه ایستا رفتار نمیکنند شما چیزی را از دست نمیدهید، اما در موارد دیگر سبک سنگینی بین ایمنی و خلاصهنویسی بوجود میآید. به منظور بهتر کردن این مطلب و همچنین برآورده کردن یکی از اهداف طراحی C#، در هر فراخوانی به شما اجازه داده میشود تا از این رفتار پویا استفاده کنید یا اگر لزومی نداشت از آن استفاده نکنید.
نوع پویا (The dynamic type)
C# 4.0 نوع استاتیک جدیدی با نام پویا (dynamic) را معرفی کرده است. زمانی که شما یک شئ از نوع پویا دارید میتوانید عملیاتهایی را روی آن انجام دهید که فقط در زمان اجرا اعمال میشوند:
dynamic d = GetDynamicObject(…);
d.M(7);
کامپایلر C# به شما این اجازه را میدهد که متدی با هر نام و آرگومانی توسط شئ d فراخوانی کنید، چون این شئ از نوع پویاست. در زمان اجراست که شئ واقعیی که d به آن اشاره داشت برای فراخوانی متد M آزمایش میشود.
گونه پویا را میتوان بعنوان نسخه ویژهای از گونه object در نظر گرفت که اعلام میکند این شئ را میتوان به صورت پویا مورد استفاده قرار داد. به سادگی میتوان از رفتار پویا استفاده کرد یا از کنار آن رد شد. هر شيئي به صورت ضمنی قابل تبدیل به حالت پویا است و در این حالت تا زمان اجرا آن را به حالت تعلیق در میآوریم. در مقابل، میتوان عبارات از نوع پویا را نیز به صورت ضمنی به object یا هر گونه دیگری در زمان اجرا تبدیل نمود.
dynamic d = 7; // compile-time implicit conversion
int i = d; // runtime implicit conversion

عملیاتهای پویا (Dynamic operations)
نه تنها فراخوانی متدها، بلکه دسترسی به فیلدها و خصوصیات، اندیکسرها و عملگرها و حتی نمایندهها (Delegates) و سازندهها را نیز به صورت پویا انجام داد:
dynamic d = GetDynamicObject(…);
d.M(7); // calling methods
d.f = d.P; // getting and settings fields and properties
d["one"] = d["two"]; // getting and setting through indexers
int i = d + 3; // calling operators
string s = d(5,7); // invoking as a delegate
var c = new C(d); // calling a constructor

نقش کامپایلر C# در اینجا فقط بستهبندی اطلاعات ضروری در مورد عملیاتهایی است که شئ d انجام میدهد و در زمان اجرا با توجه به شيئي که d به آن اشاره دارد عملیات مورد نظر انتخاب و اعمال میشود. میتوان این موضوع را بعنوان قسمت خاصی از کار کامپایلر برای زمان اجرا در نظر گرفت.
نتیجه هر عملیات پویا از نوع پویا خواهد بود به غیر از دو مورد استثناء:
ü گونه حاصل از فراخوانی یک سازنده پویا همانند گونه ساخته شده میباشد.
ü گونه حاصل از تبدیل ضمنی یا غیر ضمنی یک گونه پویا از نوع گونه مقصد میباشد.

جستجوگر زمان اجرا (Runtime lookup)
در زمان اجرا عملیاتهای پویا با توجه به ماهیت شئ مورد نظرd فراخوانی میشوند :
1- اشيا پویا (Dynamic objects)
اگر d رابط IDynamicMetaObjectProvider را پیادهسازی کرده باشد، یک شئ به اصطلاح پویا نامیده میشود، که به این معنی است که به خود اشاره داشته و عملیاتهای مربوط به خود را انجام میدهد. بنابراین با پیادهسازی رابط IDynamicMetaObjectProvider یک گونه میتواند بهطور کامل، دوباره معنای عملیاتهایی همانند فراخوانی متدها، دسترسی اعضاء و غیره را تعریف نماید. این موضوع به شدت توسط زبانهای پویا مانند IronPython و IronRuby برای پیادهسازی مدلهای اشيا پویا مورد استفاده قرارگرفته است. همچنین برنامهنویسی پویا توسط رابطهای برنامه کاربردی (API)، رابطهای Silverlight HTML DOM برای دسترسی مستقیم به خصوصیات اشيا و متدها به جای روشهای دستیابی مبتنی بر رشته مانند SetProperty یا Invoke مورد استفاده قرارگرفته است.
2- اشيا COM
اگر d یک شئ COM باشد، عملیاتهای مربوط به d از طریق COM IDispatch انجام میشود. در این صورت امکان فراخوانی گونههای COMی که دارای اسمبلی تعاملی اصلی (Primary Interop Assembly PIA) نیستند و خصوصیات COMی که در C# معادل ندارند همانند ویژگیهای پیشفرض، فراهم میشود.
3- اشيا ساده
در غیر اینصورت اگر d یک شئ استاندارد .NET باشد، آنگاه عملیاتها با استفاده از انعکاس بر روی آن نوع اعمال میشود و مقیدساز زمان اجرای C# است که عملیات پیدا کردن و سربارگذاری قواعد زمان اجرا را انجام میدهد.
4- در اصل این مقیدساز زمان اجرا، بخشی از کامپایلر C# است که بعنوان یک کامپوننت، برای اتمام کار عملیاتهای پویا که بوسیله کامپایلر ایستا معوق شده بود، در زمان اجرا عمل میکند.
مثال کد زیر را در نظر بگیرید :
dynamic d1 = new Foo();
dynamic d2 = new Bar();
string s;
d1.M(s, d2, 3, null);

از آنجا که گیرنده و آرگومان استفاده شده در فراخوانی M پویا هستند، بنابراین کامپایلر C# سعی در یافتن معنی و نحوه فراخوانی انجام شده نخواهد کرد و در عوض این اطلاعات را برای زمان اجرا به حال خود رها میکند. اطلاعاتی که کامپایلر در این مرحله جمع آوری میکند معمولاً چیزی همانند مطالب زیر است:
"فراخوانی متد M با آرگومانهای زیر توسط نمونهای از شئ d1 انجام شود:
1- یک رشته
2- یک شئ dynamic
3- مقدار 3 به عنوان یک int
4- مقدار null بعنوان یک object
در زمان اجرا، اگر تصور کنیم که گونه Foo که نوع واقعی d1 است، پویا نباشد، در این حالت مقیدساز زمان اجرای C# بر اساس اطلاعات گونهها در زمان اجرا برای اتمام کار به صورت زیر عمل مینماید:
1- از انعکاس برای بدست آوردن گونههای واقعی دو شئ d1 و d2 که نوع ایستا ندارد، در زمان اجرا استفاده میشود. نتیجه گونه Foo برای d1 و گونه Bar برای d2 است.
2- جستجو و تفکیک سربارگذاریها برای یافتن متدی با شکل M (string, Bar, 3, null) در گونه Foo انجام میشود.
3- اگر متد پیدا شد فراخوانی میشود، در غیر اینصورت یک استثنا زمان اجرا پرتاب میگردد.
تفکیک سربارگذاریها با استفاده از آرگومانهای پویا (Overload resolution with dynamic arguments) حتی اگر دریافتکننده فراخوانی متد، از گونه ایستا باشد، باز هم امکان اجرای تفکیک سربارگذاریهای وجود دارد. این وضعیت زمانی پیش میآید که یک یا چندین آرگومان از نوع پویا باشند:
Foo foo = new Foo();
dynamic d = new Bar();
var result = foo.M(d);

مقیدساز زمان اجرای C#، از بین سربارگذاریهای متد M در Foo بر اساس گونه d در زمان اجرا که در اینجا Bar است یکی را انتخاب مینماید. نتیجه این عملیات باز از نوع dynamic خواهد بود.

The Dynamic Language Runtime
یکی از کامپوننتهای مهم در بطن پیادهسازی انقیاد پویا، Dynamic Language Runtime (DLR) است که API جدیدی در .NET 4.0 به حساب میآید.
DLR نه تنها بیشترین زیر ساخت را در انقیاد پویا در زبان C# فراهم میسازد، بلکه تکامل چندین زبان برنامهنویسی پویا در .NET همانند IronPython و IronRuby را مهیا ساخته است. گرچه از طریق این زیر ساخت رایج، اطمینان از کسب سطح بالایی از تعامل و همکاری حاصل شده است، به همان میزان DLR مکانیزمهای کشکردن بسیارخوبی را مهیا ساخته که به منظور افزایش کارایی RunTime Dispatch به خدمت گرفته میشوند.
برای کاربرانی که از انقیاد پویا در C# استفاده میکنند، DLR به غیر از کاربردهای بهبود یافته قابل مشاهده نیست. اگر شما خواستار پیادهسازی اشيا توزیعکننده خود به صورت پویا هستید، رابط IDynamicMetaObjectProvide تعامل و همکاری با DLR و تعریف رفتارهای خاص برای این اشيا را امکان پذیر میسازد. انجام این عمل به صورت مستقیم شما را ملزم به درک قسمت اعظمی از کارهای درونی DLR میسازد. خوشبختانه .NET 4.0 چندین کلاس کمکی برای سادهسازی این عمل را مهیا ساخته است.

محدودیتها
محدودیتها و موضوعاتی وجود دارند که نحوه کارکرد آنها ممکن است مطابق انتظار شما نباشد:
ü DLR امکان ایجاد اشيا از اشيا دیگر که نمایانگر کلاسها هستند را اجازه میدهد. اگر چه نسخه جاری C# ساختار (Syntax) لازم برای پشتیبانی از این امر را ندارد.
ü انقیاد پویا قادر به پیدا کردن متدهای الحاقی نمیباشد. خواه متدهای الحاقی به کار برده شوند یا نه به محتوای استاتیک فراخوانی وابسته هستند.
ü توابع بی نام (همانند عبارات lambda) نمی توانند بعنوان آرگومان در یک عملیات پویا ظاهر شوند. کامپایلر توانایی انقیاد توابع بینام بدون اطلاع از گونهای که به آن تبدیل شده است را ندارد.
یکی از نتایج این محدودیتها اینست که شما نمیتوانید به آسانی پرسوجوهای LINQ را بر روی اشيا پویا اعمال کنید:
dynamic collection = …;
var result = collection.Select(e => e + 5);

اگر متد Select یک متد الحاقی باشد، انقیاد پویا نمیتواند آنرا بیابد، حتی اگر این متد یک متد نمونه باشد، کد بالا کامپایل نمیشود، چون عبارت Lambda به صورت یک آرگومان قابل ارسال به یک عملیات پویا نیست.

آرگومانهای نامگذاری شده و پارامترهای اختیاری
آرگومانهای نامگذاری شده و پارامترهای اختیاری در واقع دو ویژگی مجزا هستند، اما اغلب با هم بسیار مفید واقع میشوند. پارامترهای اختیاری به شما اجازه حذف آرگومانها در زمان فراخوانی آنها را میدهند، در حالی که آرگومانهای نامگذاری شده راهی برای ارسال آرگومانها، بر اساس نام پارامترهای معادل با آنها به جای مکان پارامتر در لیست پارامترها میباشند.
بعضی از APIها همانند APIهای اتوماسیون اداری، بهطور خاصی با پارامترهای نامگذاری شده و اختیاری نوشته شدهاند تا بهتر به خاطر سپرده شوند. تا قبل از این فراخوانی این APIها از داخل C# کار سختی بود، چون اغلب اوقات مجبور به ارسال آشکار آرگومانهایی هستیم که اکثر آنها را با مقادیر پیشفرض میتوان حذف نمود.
حتی در APIهایی که برای .NET نوشته میشوند، بعضی اوقات مجبورید که سربارگذاریهای زیادی برای پوشش ترکیب متفاوت پارامترها ارائه دهید. پارامترهای اختیاری جایگزین خوبی برای چنین مواردی هستند.

پارامترهای اختیاری
یک پارامتر به سادگی با مشخص کردن مقدار پیشفرض به یک پارامتر اختیاری تبدیل میشود:
public void M(int x, int y = 5, int z = 7);

در اینجا y و z پارامترهای اختیاری هستند و میتوان آنها را در فراخوانیها در نظر نگرفت:
M(1, 2, 3); // ordinary call of M
M(1, 2); // omitting z – equivalent to M(1, 2, 7)
M(1); // omitting both y and z – equivalent to M(1, 5, 7)

مقادیر پیشفرض آرگومانها تا حدودی محدودکننده هستند. آنها را باید به صورت مقادیر ثابت یا عباراتی به صورت default(T) مشخص نمایید.

آرگومانهای اختیاری و نامگذاری شده
C# 4.0 اجازه حذف آرگومانها بین کاما را نمیدهد مثلا M(1, ,3) . این موضوع باعث بالا رفتن خوانایی با استفاده از کاما میشود، در عوض اگر شما بخواهید آرگومانی را از وسط لیست حذف کنید میتوانید با استفاده از آرگومانهای نامگذاری شده این کار را انجام دهید. مثلاً اگر شما میخواهید فقط y را در فراخوانی M حذف کنید به صورت زیر این کار قابل انجام است:
M(1, z: 3); // passing z by name

یا
M(x: 1, z: 3); // passing both x and z by name

یا حتی
M(z: 3, x: 1); // reversing the order of arguments

هر سه شکل معادل هستند، اما نکته جالب توجه این است که در شکل سوم ترتیب آرگومانها عوض شده است. به غیر از متدها شما از آرگومانهای اختیاری و نامگذاری شده میتوانید در اندیکسرها و سازندهها نیز استفاده کنید.

تفکیک سربارگذاریها
آرگومانهای اختیاری و نامگذاری شده بر روی تفکیک سربارگذاریها نیز به صورت بسیار سادهای تأثیر میگذارند:
تفکیک سربارگذاریها زمانی قابل انجام است که یک امضا (Signature) از متد یا تمام پارامترهایش اختیاری باشند یا به ازای هر کدام از آنها یک آرگومان (از طریق نام یا از طریق مکان آن) در زمان فراخوانی متد ارائه شده باشد.
قوانین بهتر تبدیل تنها برای آرگومانهای که صریحاً ارسال میشوند، به کار برده میشود- آرگومانهای اختیاری حذف شده به منظور بهتر بودن نادیده گرفته شدهاند.
اگر دو امضاء یک متد مشابه باشند، امضایی که پارامترهای اختیاری را حذف نمیکند ترجیح داده میشود.
M(string s, int i = 1);
M(object o);
M(int i, string s = “Hello”);
M(int i);
M(5);

توسط سربارگذاریهای بالا میتوانیم نحوه عملکرد این قوانین را ببینیم. شکل M(string , int) قابل اجرا نیست چون 5 به رشته تبدیل نشده است. شکل M(int, string) قابل اجراست چون دومین پارامتر آن اختیاری است و به همین منوال M(object) و M(int) قابل اجرا خواهند بود.
M(int, string) و M(int) هر دو بهتر از M(object) هستند، چون تبدیل از 5 به int خیلی بهتر از تبدیل از 5 به object است.
در نهایت M(int) بهتر از M(int, string) است، چون آرگومانهای اختیاری حذف شده است، بنابراین متدی که فراخوانی میشود M(int) است.

ویژگیهایی برای تعامل و همکاری COM(Features for COM Interop)
انقیاد پویا همانند پارامترهای اختیاری و نامگذاری شده تجربه تعامل و همکاری با APIهای COM مانند APIهای اتوماسیون اداری را به صورت گستردهای بهبود میبخشد. به منظور حذف سرعتگیرهای باقیمانده، دو مورد ویژگی خاص COM در C# 4.0 اضافه شده است.

کامپایل بدون PIAs
Primary Interop Assemblies اسمبلیهای بزرگی در .NET هستند که از رابط COM برای بهبود تعامل گونههای قویا نوعبندی شده تولید شدهاند. PIAها پشتیبانی خوبی را در زمان طراحی فراهم میکنند به شکلی که تجربه شما از تعامل به خوبی گونههایی است که قبلاً در .NET تعریف شدهاند.
ویژگی PIA تعبیه شده، به شما اجازه استفاده از PIAها در زمان طراحی بدون داشتن آنها را در زمان اجرا میسر میسازد. در عوض کامپایلر C# قسمت کوچکی از PIA را آماده میکند که برنامه به صورت مستقیم داخل اسمبلی خود از آن استفاده میکند و در زمان اجرا PIA لازم نیست بارگذاری شود.

واردات پویا (Dynamic Import)
بسیاری از متدهای COM گونههای متغییر را قبول و بر میگردانند، که این گونهها در درون PIAها به شکل object نمایش داده شدهاند. در اکثر موارد، برنامهنویسی که این متدها را فراخوانی میکند از نوع استاتیک شئ بازگشتی متن خبر دارد، اما برای استفاده از آن اطلاعات، نیاز به انجام تبدیل صریح بر روی نوع بازگشتی دارد. این تبدیلات بسیار رایج هستند و ناراحتی فراوانی را بوجود میآورند.
به منظور داشتن تجربهای بهتر، اگر شما وارد کردن APIهای COM به همراه PIAهای تعبیه شده را ترجیح میدهید، گونههای متغییر در این حالت به وسیله نوع پویا مشخص میشوند. به عبارت دیگر، از نقطه نظر شما، امضاءهای COM از نوع dynamic به جای object در درون خود استفاده میکنند.
این بدان معنی است که شما میتوانید به آسانی و به صورت مستقیم به اعضای یک شئ بازگشتی دستیابی داشته باشید و یا آنرا به یک متغیر محلی از نوع قوی، بدون انجام تبدیلات، نسبت دهید، به منظور درک بیشتر مطلب شما میتوانید از گزینه زیر:

excel.Cells[1, 1].Value = "Hello";

به جای
((Excel.Range)excel.Cells[1, 1]).Value = "Hello";
و
Excel.Range range = excel.Cells[1, 1];
بجای
Excel.Range range = (Excel.Range)excel.Cells[1, 1];
استفاده کنید.

حذف ref
بخاطر تفاوت مدلهای برنامهنویسی، بسیاری از APIهای COM شامل پارامترهای ارجاعی بسیاری هستند.
از این رو برای برنامهنویس غیرمنطقی به نظر میرسد تا برای هرکدام از پارامترهای ref متغییرهای محلی تعریف کند و آنها را به صورت ref ارسال نماید. درعوض کامپایلر C# بخصوص برای متدهای COM این اجازه را میدهد که مقدار آرگومانها را برای پارامترهای مرجعی ارسال کنید و کامپایلر به صورت اتوماتیک متغییرهایی را برای نگهداری مقادیر ارسالی ایجاد کرده که نهایتاً در انتهای فراخوانی آنها را از بین خواهد برد.
با این روش برنامهنویس برنامه را به صورت فراخوانی با مقدار مینویسد، اما در اصل همان فراخوانی با ارجاع اعمال میشود.

خصوصیات ایندکسگذاری شده
بسیاری از APIهای COM خصوصیات ایندکسگذاری شدهای دارند که ضرورتاً این خصوصیات دارای پارامترهایی هستند. C# به شما اجازه تعریف خصوصیات ایندکسگذاری شده را نمیدهد، اما برای توسعه API غیر C# اجازه دسترسی به این خصوصیات را با استفاده از ساختار دستیابی عناصر داده است. بنابراین به جای
o.set_P(i+1, o.get_P(i) * 2);
شما میتوانید به صورت واضحتری همانند زیر بنویسید
o.P[i+1] = o.P[i] * 2;

محدودیتها
تعداد کمی از ویژگیهای رابط COM هنوز در C# در بر گرفته نشدهاند، مهمترین آنها خواص پیشفرض است. همانطور که در بالا ذکر شد این امر اگر به صورت پویا به COM دسترسی داشته باشید، در نظر گرفته خواهد شد، ولی باز هم با این وجود کدهای C# استاتیک آنها را نمیشناسند.


مثال بهتری از COM
در اینجا مثال بهتری از اتوماسیون توسط Office نشان داده میشود که بسیاری از خصوصیات جدید موجود در C# را در عمل نشان میدهد.
using System;
using System.Diagnostics;
using System.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word;
class Program
{
static void Main(string[] args) {
var excel = new Excel.Application();
excel.Visible = true;
excel.Workbooks.Add(); // optional arguments omitted
excel.Cells[1, 1].Value = "Process Name"; // no casts; Value dynamically
excel.Cells[1, 2].Value = "Memory Usage"; // accessed
var processes = Process.GetProcesses()
.OrderByDescending(p =&gt; p.WorkingSet)
.Take(10);
int i = 2;
foreach (var p in processes) {
excel.Cells[i, 1].Value = p.ProcessName; // no casts
excel.Cells[i, 2].Value = p.WorkingSet; // no casts
i++;
}
Excel.Range range = excel.Cells[1, 1]; // no casts
Excel.Chart chart = excel.ActiveWorkbook.Charts.
Add(After: excel.ActiveSheet); // named and optional arguments
chart.ChartWizard(
Source: range.CurrentRegion,
Title: "Memory Usage in " + Environment.MachineName); //named+optional
chart.ChartStyle = 45;
chart.CopyPicture(Excel.XlPictureAppearance.xlScre en,
Excel.XlCopyPictureFormat.xlBitmap,
Excel.XlPictureAppearance.xlScreen);
var word = new Word.Application();
word.Visible = true;
word.Documents.Add(); // optional arguments
word.Selection.Paste();
}
}
این کد نسبت به کد همتای خود در C# 3.0 بسیار خواناتر و مختصرتر است.

واریانس
جنبهای از ژنریک که اغلب تعجبآور است، اشتباه بودن کدهای زیر است:

IList<string> strings = new List<string>();
IList<object> objects = strings;

نسبتدهی دوم اشتباه است چرا که strings عناصر یکسانی با object ندارند. یک دلیل بسیار خوب برای این امر وجود دارد. اگر این امر اجازه داده میشد، شما میتوانستید کد زیر را بنویسید:
objects[0] = 5;
string s = strings[0];

این کد به یک int اجازه میدهد که به لیستی از رشتهها وارد شود و به تبع به عنوان یک رشته خارج شود و این باعث نقض امنیت انواع میگردد.
اگر چه رابطهای مشخصی برای جلوگیری از وقوع این امر وجود دارد، اما توجه داشته باشید که هیچ راهی برای درج یک object در درون Collection وجود ندارد. یکی از این رابطها IEnumerable<T> است. اگر به جای آن شما بگویید:
IEnumerable<object> objects = strings;

کدها بسیار ایمنتر میشوند: هیج راهی وجود ندارد که ما بتواینم نوع دیگری را از طریق object درون string قرار دهیم، چرا که Object متدی برای دریافت یک عنصر به عنوان ورودی ندارد.
 
پاسخ
  


پرش به انجمن:


Browsing: