C# Programming Guide
193 subscribers
113 photos
9 videos
14 files
102 links
سلام دوستان در این کانال نکاتی در مورد مسائل پیشرفته در سی شارپ ارائه میشه که مربوط به بیش از 15 سال تجربه ی کاری من هست.
ممنون از اینکه دنبال میکنید.
اگر نکات خاصی به ذهنتون رسید با ادمین در میون بذارید
تماس با ادمین:
@Ali_Visual_Studio
Download Telegram
کاهش عملیات Boxing و Unboxing در کد:



عملیات boxing و unboxing یک عملیات داخلی فریم وروک است که برای برنامه نویسان C#.Net و VB.Net خودکار انجام میشود و اصلاً متوجه آن نمیشوند (ولی مثلاً برنامه نویسان VC++.Net مجبوراً صراحتاً دستور مربوطه را بنویسند)

دات نت زبانی کاملاً شی گرا است و تا انجا پیش رفته که Struct های ان نیز مطابق اصول شی گرایی هستند ...
تمام Struct های دات نت وراثتی هستند از System.ValueType و آن هم وراثتی است از System.Object

بدین ترتیب سلسه مراتب وراثتی برای Struct ها هم تامین شده که گاهاً میتواند باعث تعجب برنامه نویسان سایر زبانهای شی گرایی گردد.

این کار محاسن زیادی دارد و اجازه شی گرایی یکپارچه را در زبان برنامه نویسی میدهد و خیلی خوب است .

ولی اصول مدیریت داخلی حافظه برای Struct ها با Class ها بسیار بسیار فرق دارد و این در اصل سرچشمه تفاوت این دو ساختار است که من قصد و وقت تشریح ان را ندارم و تاثیری هم در کد ما ندارد.

نکته ای که مهم است ان جا است که دات نت چطور میتواند یک Struct را با یک سیستم مدیریت حافظه متفاوت در یک Object که Class است جای دهد؟؟؟

کنترل این عملیات به صورت خودکار بر عهده محیط CLR است و نام این عملیات box و unbox است.

عمل boxing چیزی شبیه این است ... (شبیه است ولی این طوری نیست!)
کد:

public class box
{
public structtype value;
}

//....

structtype value1 = ...;
object value2 = new box() { value = value1 };

که طی آن یک struct (مثل value1) به یک class (مثل value2) تبدیل میشود.


عمل unboxing چیزی شبیه این است ... (شبیه است ولی این طوری نیست!)
کد:

public class box
{
public structtype value;
}

//....

object value2 ...;
structtype value1 = ((box)value2).value;

که طی آن یک struct که داخل یک object است (مثل value2) به یک struct واقعی و آزاد (مثل value1) تبدیل میشود.

نکته مهم و قابل توجه انجا است که عملیات فوق بسیار بسیار پرسرعت و با بازدهی بالا است و اصلاً با کدهایی که دیدید برابر نیست و مستقیم و با سرعت بالا توسط هسته CLR انجام میشود و در هر اجرای یک کپی بسیار کوچک اطلاعات به حجم Struct هم رخ میدهد.

ولی با وجود پرسرعت بودن، انجام عمل فوق در یک حلقه عظیم میتوانید باعث افت سرعت شود،
مجدد تاکید میکنم که حلقه ای 100 بار انجام شود سرعت را 100 برابر کاهش میدهد و حلقه 1000 و 10000 و ... هم جای خود و در نهایت افزایش صفر مشکل ساز میشود.

کد عملی مثل این نمونه از boxing و unboxing است:
کد:

int v1 = ...;
object v2 = v1;
int v3 = (int)v2;

البته کد فوق به ذات مشکل خاص سرعتی ندارد ولی در حلقه ای که چند صفر ناقابل به ان اضافه کند ... !

ولی کد زیر اصلاً boxing و unboxing نیست : (گرچه ظاهرش یکسان است!)
کد:
string v1 = ...;
object v2 = v1;
string v3 = (string)v2;

چون کد اول Integer بود و Integer یک Struct است ولی String خودش یک Class است و نیازی به boxing ندارد.

نتیجتاً شما باید تا حد امکان از پاسکاری Struct ها به Object ها جلوگیری کنید.

=====

همانطور که اول گفتم شما باید مراقب کدنویسی داخلی ناپیدا توابع آماده هم باشید.
مثلا کد ساده زیر را در نظر بگیرید ...
کد:

//C#.Net
int[] array = new int[512];

int item = 0;
for (int index = array.Length -1 ; index >= 0; —index)
{
array[index] = item++;
}
//...
//بحث اصلاً سر کدهای قبلی تا این نوشته نیست
//...


System.Array.Sort(array);

یک کد ساده مختصر مفید و در اصل یک خطی برای مرتب کردن عناصر یک آرایه ... فقط یک خط ! (فقط تک خط آخری)
حالا اگر بگم تک خط کد فوق در بدترین شرایط باعث ...
- دو حلقه تو در تو مقایسه با حدود 130 هزار مقایسه ...
- 260 هزار box ...
- 260 هزار unbox ...
- جابه جایی و انتقال نزدیک 2MB اطلاعات در RAM میشود ...
حالا چه فکر میکنید؟؟؟

حالا فکر کنید (در unity و بازی سازی) قرار باشد کد فوق در متدی مثل Game.Update قرار داشته باشد و قرار باشد در هر ثانیه 60 باری اجرا شود !!!
برنامه شما در یک ثانیه 120MB اطلاعات را فقط به خاطر همین یک خط دستور در RAM جابه جا خواهد کرد!
حتماً باز هم میگید چرا برنامه کند است!!!

یادتان نرود اکثر کدهای برنامه نویسی شما همان تعداد خط کد ظاهری که شما تایپ میکنید نیستند.

(الگوریتم مرتب سازی یک چیز کلی و استاندارد در همه زبانها است و قرار نیست کاری در مریخ انجام شود، اگر دستور اجرا میکنید نباید انتظار داشته باشید که با جادو و دستور در یک آن در CPU اجرا شود، برای انجام عملیاتها یا شما باید الگوریتم را بنویسید یا کس دیگری قبلاً آن را نوشته و در هر دو صورت این الگوریتم هزینه ای برای اجرا دارد.)
توی سی شارپ 7 شما میتونید برای یک تابع چندین خروجی متفاوت بدید، قبلا اینطور بود که شما همیشه باید یک خروجی میداشتید و در نهایت اگر پارامتر هاتون زیاد باشه مجبورین کلاس بسازید و پارامتر های خروجی رو توی اون کلاس بریزید ولی توی سی شارپ نسخه ی 7 (ویژوال استادیو 2017) شما میتونید برای یک تابع چند خروجی داشته باشید.

برای مثال:
در نظر داشته باشید که برای استفاده از این سیستم باید پکیج System.ValueTuple رو نصب کرده باشید روی پروژتون
برای اینکه بتونید همیشه سریع کد بزنید سعی کنید عادت کنید به استفاده از Code Snippets ها، قطعه کد ها به شما کمک میکنن تا با تایپ چند کاراکتر و سپس استفاده از دابل تب کد کامل براتون تایپ بشه در این حالت شما میتونید مقادیر رو هم تعویض کنید.در ادامه یک ویدئوی کوتاه براتون میذارم که بدونید از Code Snippets ها چطوری استفاده کنید.دابل تب به این معنی هست که شما کلید Tab کیبرد رو دوبار پشت سر هم بزنید.
This media is not supported in your browser
VIEW IN TELEGRAM
انواع Code Snippets ها رو میتونید از لینک مایکروسافت ببینید:

https://msdn.microsoft.com/en-us/library/z41h7fat.aspx
همیشه وقتی میخواید از یک لیستی آیتم های خاصی رو دریافت کنیدبهتره که از Linq استفاده کنید، هم راحت تره هم خوانا تره هم باعث میشه رفع باگ و مشکل براتون راحت تر باشه، قدیم ها که Linq نبود ما همیشه مجبور بودیم از for و foreach استفاده کنیم یا حتی اینارو تو در تو هم بنویسیم.
C# Programming Guide
همیشه وقتی میخواید از یک لیستی آیتم های خاصی رو دریافت کنیدبهتره که از Linq استفاده کنید، هم راحت تره هم خوانا تره هم باعث میشه رفع باگ و مشکل براتون راحت تر باشه، قدیم ها که Linq نبود ما همیشه مجبور بودیم از for و foreach استفاده کنیم یا حتی اینارو تو در…
شما میتونید انواع شرط ها و کوئری هایی که میخواید رو توی Linq بزنید و حتی میتونید خروجی مورد نظرتون رو هم به کلاس دیگه یا یک کلاس dynamic جدید تغییر بدید در این صورت فقط کافیه دستور اخر select رو تغییر بدید تا خروجی مورد نظرتون تغییر کنه مثلا بنویسید:
select new {x.Name,Age=x.Age}
آیا interface ها همیشه برای مرتب سازی و زیبا سازی و بالا بردن خوانایی پروژه طراحی و ساخته میشن یا اینکه در مواقعی هم روی پرفرمنس و سرعت پردازش اطلاعات میتونن تاثیر گذار باشند؟
#Interface
#Performance
C# Programming Guide
Photo
گاهی وقت ها برای راحتی کار خودمون عملا همیشه در حال استفاده از enum ها و type های مختلف هستیم در حالی که به عملیات محاسباتی که میرسه همیشه مجبور میشیم شرط های اضافه بذاریم.این قضیه علاوه بر اینکه کد مارو از حالت زیبا بودن و تمیز بودن خارج میکنه در پروژه های خیلی بزرگ باعث افت سرعت خواهد شد، افت سرعتی که شاید چیزی رو کند نکنه ولی از نظر یک برنامه نویس حرفه ای میتونست این افت هم وجود نداشته باشه.
C# Programming Guide
Photo
برای مثال کد بالا میتونست به این صورت هم نوشته بشه، تفکیک کلاس ها + تفکیک عملیات محاسباتی که سیستم مجبور نباشه هر بار که بخواد محاسبات رو انجام بده مجدد یه چیزی رو بررسی کنه.
مثال صدا زدن توابع
دوستانی که WPF کار میکنن و نرم افزار های دسکتاپ مینویسن این ویدئو رو پیشنهاد میکنم حتما ببینن:
https://www.youtube.com/watch?t=28&v=c_AB_XSILp0
C# Programming Guide
دوستانی که WPF کار میکنن و نرم افزار های دسکتاپ مینویسن این ویدئو رو پیشنهاد میکنم حتما ببینن: https://www.youtube.com/watch?t=28&v=c_AB_XSILp0
همونطور که میبینید شما میتونید با ساختار XAML در wpf براحتی برای مک و لینوکس هم نرم افزار طراحی کنید در واقع یک طرح میزنید و روی ویندوز و مک و لینوکس اجرا میکنید.
C# Programming Guide
ابن پروژه هم پیشنهاد میکنم بهش نگاه بندازید: https://www.cshtml5.com/
با این هم میتونید با همون ساختار WPF و XAML طراحی سایت کنید...
پروژه ی اپن سورسی هست به نام SignalGo که ارتباط بلادرنگ یا همون Real-Time رو براتون خیلی آسون میکنه که میخوام از این پس بیشتر در موردش صحبت کنیم.این پروژه ای هست که یکی دو سالی میشه طراحی و و پیاده سازیش کردم و طراحی یک سرور و ارتباط کلاینت با اون رو برای شما بقدری آسون و سریع میکنه که میتونید باهاش یک سرور با بیش از صدها جدول و توابع رو کمتر از یک ماه پیاده سازی کنید و ده ها سرور رو همزمان مدیریت کنید بدون اینکه دغدغه مشکلات ودسترسی ها و امنیت و سرعت و ... داشته باشید.