Exploring the Features of C# 11: The Modern Capabilities of a Vibrant Language [Webinar]
C# has evolved long since its introduction about 20 years ago. In this live-coding presentation, learn about the fascinating features of the most recent version of the language. We will explore the most interesting features, their power, and how we can benefit from them to create concise, expressive, and maintainable code.
شروع کار با تکنولوژی های وب
انتشار Node.js Tools در GitHub
کتابخانه Simple 3D Coverflow
Simple 3D Coverflow is a fully 3D multimedia coverflow slider plugin that allows to display multimedia content with an unique original layout from a 3D perspective. It’s perfect for any kind of presentation, for anyone that wants to deliver a great impact to thier visitors. It runs on all major browsers and mobile devices like iPhone, iPad, IOS, Android and Windows. When a thumbnail is clicked you can choose to do nothing, display multimedia content using our great revolution lightbox or to open a new webpage.
مدل Actor با استفاده از Akka.net
In the same time when first object-oriented languages were emerging, another concept inspired by general relativity and quantum mechanics was taking shape – actor model. In general terms, the Actor model was defined 1973. and was developed on a platform of multiple independent processors in a network. Similar to the object-oriented approach, this essentially mathematical model, revolved around the concept of actors. An actor is the smallest structural unit of Actor model, and just like objects, they encapsulate data and behavior. In difference to objects, however, actors communicate with each other exclusively trough messages. Messages in actors are processed in a serial manner. According to the full definition of actors, they can do three things:
- send a finite number of messages to other actors
- create a finite number of new actors
- designate the behavior to be used for the next message it receives
مفاهیم برنامه نویسی ـ مروری بر کلاس و شیء
به زبان ساده، وقتی شما متغیر جدیدی را ایجاد میکنید، با توجه به نوع (Type) آن متغیر، "مقدار" متغیر شما در Stack یا Heap قرار خواهد گرفت.
Stack
این ساختمان داده، داخل Memory پیاده سازی شده است و تعدادی از متغیرهایی را که ما داخل کد ایجاد میکنیم، در این نوع ساختمان داده از Memory نگهداری میشوند.
شرط قرار گرفتن مقدار یک متغیر داخل Stack این است که متغیر از نوع Value Type باشد. در زبان #C، بطور کلی Struct و Enumها Value Type هستند و بصورت پیشفرض داخل Stack قرار میگیرند. تمامی ValueTypeها در #C، بطور implicit از System.ValueType ارث بری میکنند.
Typeهای زیر، Value Typeهای پیشفرض تعریف شدهی در زبان #C هستند که به آنها Simple Type نیز گفته میشوند:
Represents | Type |
Boolean value | bool |
8-bit unsigned integer | byte |
16-bit Unicode character | char |
128-bit precise decimal values with 28-29 significant digits | decimal |
64-bit double-precision floating point type | double |
32-bit single-precision floating point type | float |
32-bit signed integer type | int |
64-bit signed integer type | long |
8-bit signed integer type | sbyte |
16-bit signed integer type | short |
32-bit unsigned integer type | uint |
64-bit unsigned integer type | ulong |
16-bit unsigned integer type | ushort |
اگر سورس هرکدام از این تایپها مانند Int32 را در ریپازیتوری CoreFX مایکروسافت بررسی کنید، متوجه خواهید شد که تمامی این تایپها از نوع Struct تعریف شدهاند و همانطور که گفتیم، بطور پیشفرض، Structها داخل Stack قرار خواهند گرفت.
طول عمر متغیرهایی که داخل Stack قرار گرفتهاند، منحصر به پایان اجرای یک متد است. بدین معنا که بعد از به پایان رسیدن یک متد، تمامی متغیرهای مورد استفاده در آن متد، از حافظه Stack بطور خودکار حذف خواهند شد. متغیرهایی که داخل Stack قرار میگیرند، نوع و حجم مقادیرشان بر اساس Type ای دارند، در زمان Compile-Time مشخص است.
public static int Add(int number1, int number2) { // number1 is on the stack (function parameter) // number2 is on the stack (function parameter) int sum = number1 + number2; // sum is on the stack (local variable) return sum; }
در زبان #C و در مرحله Compile-Time، کدها به زبان IL (مخفف Intermediate Language) ترجمه میشوند که با نامهای MSIL (مخفف Microsoft Intermediate Language ) و CIL (مخفف Common Intermediate Language ) نیز، این زبان شناخته میشود. ساختار این زبان Stack-based بوده و با شناخت آن، با مفهوم Stack نیز بهتر میتوانیم آشنا شویم.
IL زبانی است که CLR (مخفف Common Language Runtime) را که همان Runtime مایکروسافت است، شناخته و اجرا میکند. قابل ذکر است که Runtime مایکروسافت Open-Source بوده و سورس آن با نام CoreCLR در گذشته از این آدرس و در حال حاضر با نام Runtime از این آدرس قابل دسترسی است.
C:\Program Files (x86)\Microsoft SDKs\Windows\{version}\Bin\ildasm.exe
.method private hidebysig static int32 Add(int32 number1, int32 number2) cil managed { .locals init (int32 V_0, int32 V_1) IL_0001: ldarg.0 // Stack is: [2] IL_0002: ldarg.1 // Stack is: [2, 5] IL_0003: add // Stack is: [7] IL_0004: stloc.0 // Stack is: [] and V_0's value is: 7 IL_0005: ldloc.0 // Stack is: [7] IL_0006: stloc.1 // Stack is: [] and V_1's value is: 7 IL_0009: ldloc.1 // Stack is: [7] IL_000a: ret // Return [7] }
میتوانید لیست دستورات مورد استفاده در CIL را از اینجا ببینید.
در ادامه، خط به خط، خروجی حاصل را بررسی میکنیم:
2- از کلمه کلیدی ldarg (مخفف Load Argument) برای لود کردن آرگومان یا همان پارامتر ورودی متد، داخل Stack استفاده میشود.
• ldarg.0 به معنای لود کردن پارامتر ورودی اول، داخل Stack است و با فراخوانی آن، Stack Frame دارای یک عضو که مقدار آن 2 است، میشود.
3- با استفاده از کلمه کلیدی add، مقادیر موجود در Stack با یکدیگر جمع میشوند و Stack Frame دارای یک عضو که مقدار آن 7 است، میشود.
4- با استفاده از کلمه کلیدی stloc (مخفف Store Local)، آخرین عضو موجود در Stack، داخل متغیر محلی ذکر شده، قرار گرفته و ذخیره میشود.
5- با استفاده از کلمه کلیدی ldloc (مخفف Load Local)، میتوان متغیر محلی ذخیره شده را داخل Stack قرار داد.
6- در نهایت، مقدار 7، داخل متغیر 1 یا همان V_1 با دستور stloc.1 بار دیگر ذخیره، با ldloc.1 لود شده و با استفاده از دستور ret، برگشت داده میشود.
* نکته: اگر کدها را بطور دقیق بررسی کرده باشید، احتمالا فکر کرده اید که چه نیازی به ایجاد یک متغیر اضافی و ریختن نتیجه داخل آن و سپس برگشت دادن نتیجه، در مرحله 6 است؟!
* نکته: احتمالا تا به اینجا دلیل بوجود آمدن StackOverflowException را متوجه شده باشید. فضای Stack محدود است. این فضا در سیستمهای 32 بیت برابر با 1 مگابایت و در سیستمهای 64 بیت برابر با 4 مگابایت است (Reference). اگر حجم متغیرهایی که روی استک Push میشوند، این محدودیت را رد کنند و یا اگر یک متد بطور دائم خودش را صدا بزند (Recursive) و هیچگاه از آن خارج نشود، با خطای StackOverflowException مواجه میشوید.
Heap
.Heap: a group of things placed, thrown, or lying one on another
در مقابل ساختار ترتیبی و منظم Stack، ساختار Heap قرار دارد. Heap قسمتی از حافظه است که ساختار، ترتیب و Layout خاصی ندارد.
وقتی یک متغیر از نوع string را ایجاد میکنیم، مقدار آن داخل Heap و Memory-Address آن متغیر روی Heap، در Stack نگه داری میشود:
public static void SayHi() { string name = "Moien"; }
در این مثال، چون string یک class است، مقدار آن داخل heap ذخیره شده و آدرس آن قسمت (segment) از memory، روی Stack قرار میگیرد:
.method private hidebysig static void SayHi() cil managed { .locals init (string V_0) IL_0001: ldstr "Moien" // Stack is: [memory-address of string in heap] IL_0006: stloc.0 IL_0007: ret }
به متغیرهایی که مقادیرشان داخل Heap ذخیره میشوند، Reference-Type گفته میشود.
* نکته: در این مثال متغیری به نام name ایجاد شده که از آن هیچ استفادهای نشده است. در زمان JIT-Compilation، با توجه با Optimizationهای موجود در سطح CLR، این متد بطور کلی اضافه تشخیص داده شده و از آن صرفنظر خواهد شد.
Boxing and Unboxing
به فرایند تبدیل یک Value-Type مانند int که بصورت پیشفرض داخل Stack ذخیره میشود، به یک object که در داخل Heap ذخیره میشود، Boxing گفته میشود. انجام این عمل باعث allocation بر روی memory میشود که سربار زیادی دارد.
با انجام عمل Boxing، قادر خواهیم بود تا بعنوان مثال یک عدد را بر خلاف روال عادی آن، روی Heap ذخیره کنیم:
public static void Boxing() { const int number = 5; object boxedNumber = number; // implicit boxing using implicit cast object boxedNumber = (object)number; // explicit boxing using direct cast }
در ابتدا عدد 5 روی Stack ذخیره شده بود، اما با Box کردن آن، یعنی قرار دادن مقدار آن داخل یک object، مقدار از Stack به Heap انتقال داده شده و allocation اتفاق خواهد افتاد:
.method public hidebysig static void Boxing() cil managed { .locals init (object V_0) IL_0001: ldc.i4.5 // Stack is: [5] IL_0002: box [System.Runtime]System.Int32 // Stack is: [memory-address of 5 in heap] IL_0007: stloc.0 IL_0008: ret }
به عکس این عمل، یعنی تبدیل یک Reference-Type به یک Value-Type، اصطلاحا Unboxing گفته میشود:
public static void Unboxing() { object boxedNumber = 5; int number = (int)boxedNumber; }
که نتیجه آن، به این صورت خواهد بود:
.method public hidebysig static void Unboxing() cil managed { .locals init (object V_0, int32 V_1) IL_0001: ldc.i4.5 // Stack is: [5] IL_0002: box [System.Runtime]System.Int32 // Stack is: [memory-address of 5 in heap] IL_0007: stloc.0 // Stack is: [] IL_0008: ldloc.0 // Stack is: [memory-address of 5 in heap] IL_0009: unbox.any [System.Runtime]System.Int32 // Stack is: [5] IL_000e: stloc.1 // Stack is: [] IL_000f: ret }
تلاش تیمهای مایکروسافت طی سالهای اخیر، باعث افزایش Performance فوق العاده در NET Core. و ASP.NET Core شده است. یکی از دلایل این Performance، جلوگیری بسیار زیاد از allocation در کدهای خود NET. است، که این امر به واسطه اولویت قرار دادن استفاده از Structها میسر گردیده است.
برخلاف Stack که طول عمر متغیرهای موجود در آن، در انتهای یک متد پایان مییابند، متغیرهای allocate شدهی در Heap به این شکل نبوده و در صورت حذف نکردن آنها بصورت دستی، تا پایان طول عمر اجرای برنامه داخل memory باقی خواهند ماند. اینجا، جاییست که Garbage Collector در NET. وارد عمل میشود.
Domain Driven Design: The Good Parts
The greenfield project started out so promising. Instead of devolving into big ball of mud, the team decided to apply domain-driven design principles. Ubiquitous language, proper boundaries, encapsulation, it all made sense.
But along the way, something went completely and utterly wrong. It started with arguments on the proper way of implementing aggregates and entities. Arguments began over project and folder structure. Someone read a blog post that repositories are evil, and ORMs the devil incarnate. Another read that relational databases are last century, we need to store everything as a stream of events. Then came the actor model and frameworks that sounded like someone clearing their throat. Instead of a nice, clean architecture, the team chased the next new approach without ever actually shipping anything.
Beyond the endless technical arguments it causes, domain-driven design can actually produce great software. We have to look past the hype into the true value of DDD, what it can bring to our organizations and how it can enable us to build quality systems. With the advent of microservices, DDD is more important than ever - but only if we can get to the good parts.