<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های عرشیا دنیابین</title>
        <link>https://virgool.io/feed/@arshiadonyabin</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-06-16 16:18:35</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1615439/avatar/IpdQJX.jpeg?height=120&amp;width=120</url>
            <title>عرشیا دنیابین</title>
            <link>https://virgool.io/@arshiadonyabin</link>
        </image>

                    <item>
                <title>آیا رشته ReferenceType است ؟</title>
                <link>https://virgool.io/@arshiadonyabin/is-sting-reference-type-u0hrcthsjubc</link>
                <description>مظلبی  که توی این مقاله میخوام در موردش صحبت کنم شاید در نگاه اول مقداری عجیب به نظر برسه اما پیشنهاد میکنم که در خصوصش مقداری تعمل کنید.به نقل از وبسایت مایکروسافت String در واقع یک Built-in Reference Type هست.و همونطوری که میدونید C# یک زبان C - Based هست و ما در زبان C چیزی به نام string نداریم. حالا در سی شارپ ما در واقع آرایه ایی از کرکتر هارو داریم که بهش string میگیم و زیر مجموعه Namespace System.String در .NET هستش یعنی یه جورایی String ماهیت Array گونه دارد. اصلا چرا دارم اینارو میگم ؟بیاین این کد و باهم ببینیم : مقدار متغییر str به متود PassByValue پاس داده شده.ما الان اومدیم مقدار یه رشته رو دادیم به یه متودی یه مقداری رو به اون متغییر اضافه کردیم و به عبارتی مقدارش رو تغییر دادیم .. فارغ از اینکه Value Type و Reference Type چیست ؟ (اگر نمیدونید چیست میتونید به این مقاله مراجعه بفرمایید. ) سوال اینجاست که چرا مقدار این متغییر ما تغییر نکرده؟جالبه که بگیم متغیری از جنس string رفتاری دوگانه دارد چون بعد از تغییر قسمت جدید از حافظه به این متغیر اختصاص داده شده و متغیر قبلی هنوز در حافظه مقدار قبلی خود را حفظ میکند!( اگر این جمله رو متوجه نمیشوید پیشنهاد میکنم به این مقاله مراجعه کنید.)چرا این اتفاق میوفته چون در واقع متود بالا داره یه کپی از متغییر رو به متود PassByReference میده !پس وقتی یه کپی از str به متودمون برسه هر تغییری روش انجام بشه در Scope متود معتبر هست ( خط دوم خروجی ) و پس از تموم شدن متود Dispose شده و از بین میره !و زمانی که ما مقدار str رو پرینت میگیریم مقدار اولیه ابجکتی که ساخته شده رو بهمون خروجی میده ( خط سوم خروجی )حالا سوال اینجاست که چطور میتونم مقدار تغییر داده شده رو در متغییر str داشته باشم ؟به وسیله کلید واژه های out و ref :اگر بخوایم از کل نکاتی که اشاره کردیم توی یه پاراگراف نتیجه گیری کنیم میگیم که :  متغیری از جنس string از نوع Reference Type هاست چون همانطور که میدانید در Heap ذخیره میشود و زمانی که به متودی پاس داده میشود اون متود میتونه مقدار پاس داده شده رو تغییر دهد اما نمیتواند متغییر پاس داده شده رو به مقدار فعلیش Dereference کند چون صرفا یک کپی از اون متغییر رو در اختیار دارد.با تشکر از همکار خوبم امین محمدی که چند سال پیش من رو با این موضوع به چالش کشید.باشد که رستگار شویم : )) </description>
                <category>عرشیا دنیابین</category>
                <author>عرشیا دنیابین</author>
                <pubDate>Sat, 15 Jun 2024 16:40:29 +0330</pubDate>
            </item>
                    <item>
                <title>struct و ref در سی شارپ چیست ؟</title>
                <link>https://virgool.io/@arshiadonyabin/whatisstructandrefincsharp-va09vfwvuzbx</link>
                <description>ما از قدیم الیام تو سی شارپ struct رو داشتیم ، (به نقل از داکیومنت مایکروسافت)struct از نوع value type هست و بهمون کمک میکنه تا دیتا و مشتقاتش رو کپسوله کنیم ، بخوام ساده تر تعریفش کنم یک data structure  کوچیک و سبک رو برامون در نهایت به ارمغان میاره اگر سطح پایین تر هم بخوام توضیحش بدم ، زمانی که شما یک  instance  از Struct تغریف میکنید مثل اکثر متغییر های دیگه ایی که تعریف میکنید میره میشینه توی stack حافظمون،  نمونه سینتکسشم پایین میذارم : Nondestructive mutation :جهش غیر مخرب یا همون Nondestructive mutation ، با معرفی سی شارپ 10 ما میتوانیم به وسیله کلید واژه With میتونیم یک کپی از یک Instance با خواص و فیلد های مشخص برای خوردمون ایجاد کنیم به طور مثال :همچنین میتونیم به وسیله Generic Constraint ورودی تایپ و متودمون رو محدود به value type ها کنیم :مثلا Container  ما الان فقط میتونه Value Type هارو به عنوان ورودی Constructor اش بگیره (عدد ، کارکتر ، تاریخ و struct ایی که خودمون تعریف کردیم و ... ) و بدیهیه اگر به ورودی Constructor  رشته (و هر ReferenceType دیگه ایی)پاس بدیم خطا خواهیم گرفت.اگر راجع به ValueType و  ReferenceType   ها سوال دارید پیشنهاد میکنم ابتدا مقاله دیگم در این مورد رو بخونید.ما میتونیم ref struct  هم تعریف کنیم که تفاوتش با struct اینه که نمیتونیم به عنوان ارگومان به یه متود پاسش بدیم یا نمیتونیم type دیگری رو مثل class باهاش مقدار دهی کنیم.یک ref struct نمیتواند :      - المانی از یک آرایه یا کالکشن باشد.      -نمیتواند یک interface رو پیاده سازی کند.      - نمیتواند از lambda expression یا یک تابع محلی دریافت شود.      -نمیتواند در یک متود async استفاده شود (اما میتوان از اون در مفاهیم همزمانی استفاده کرد مثلا متودی که یک Task و یا Task&lt;T&gt; خروجی میدهد).           -نمیتواند در حلقه ها استفاده شود.همینطور ref struct  به نسبت struct مدت زمان کوتاه تری در حافظه میمونه ، به طور مثال شما اگر در سطوح بالاتر (خارج از Scope فعلی) یک struct تغریف کنید، تا وقتی از Scope فعلی خارج نشیم و یا به نحوی صریحا از حافظه حذفش نکنیم باقی میمونه. اما ref struct یکم لوسه : ) برای سناریو های کوتاه مدت تر تخصیص داده میشود. کاربردش زمانیه که شما به یه data structure با بازدهی بالا و طول عمر کم احتیاج دارید(مثل ایجاد کردن تعداد زیادی object) و ما ref struct رو خیلی محدود میتونیم استفاده کنیم یعنی صرفا محدود هست به scope ایی که درش تعریف شده و نمیتوان اون رو جای دیگری استفاده کرد.تو سی شارپ 11 مایکروسافت ref field رو اضافه کرده که یه هزار توی از پیچیدگی برای ref struct و کلا ref ایجاد کرده (البته از نظر من :) )برای چک کردن نال بودن یا نبودن یک ref field از Unsafe.IsNullRef&amp;amp;lt;T&amp;amp;gt;(T) استفاده میشودما میتونیم ref struct هامون رو readonly هم تعریف کنیم به سه روش ، با توجه به اینکه توضیح دادن این موضوع قطعا کمکی نمیکنه مثال کدی میزنم براش : 1- readonly ref : شما میتوانید  به وسیله =  فقط درون یک constructor  و یا تعریف اولیه آن را مقدار دهید.2-ref readonly : این دوستمون رو نمیشه به وسیله = هر جایی مقدار داد.   3-readonly ref readonlyاین دوستمون رو فقط میشه تو constructor  و تعریف اولیه اون ref reassign  کرد و هر جایی از کد هم نمیشه این کار رو کرد.اگر براتون پیچیده و سخته و متوجهش نمیشید سعی کنید ازش استفاده کنید ، واضح میشه بعد یه مدتی.. خوب باشین : )</description>
                <category>عرشیا دنیابین</category>
                <author>عرشیا دنیابین</author>
                <pubDate>Tue, 22 Aug 2023 19:50:53 +0330</pubDate>
            </item>
                    <item>
                <title>چگونه IEnumerable میتواند Performance رو نابود کند؟</title>
                <link>https://virgool.io/@arshiadonyabin/howienumerablewilldecreaseyourperformance-yff6vn9qpmvz</link>
                <description>چندی پیش به نکته ایی در فضای نت برخوردم که گفتم بهتره خودم تستش کنم و توی ویرگولم منتشرش کنم.اون هم نکته ایی در استفاده از IEnumerable بود : عرض کنم خدمت حضور انورتون که قطعا هرکسی که مقداری سی شارپ کد زده باشه کالکشن های سی شارپ رو میشناسه IEnumerable هم یکی از اون هاست فرض میکنیم ما یه دیتاسورس داریم و میخوایم از اون دیتا واکشی کنیم برای این مثال من یه فایل csv کوچیک درست کردم و میخوام ازش دیتا بخونم Data SourceData Modelتوی این مثال ما میخوایم که دیتامون رو از فایل بخونیم به مدلمون مپ کنیم و در نهایت Count اش رو بگیریم و نمایشش بدیم من داخل GetData دیتا رو از فایل خوندم کاما هاش رو جدا کردم و به صورت Deferred Execution  با yield return برش گردوندم ، اینجا میتونستیم از یه temp آبجکت استفاده کنیم و دیتا رو یکی یکی میگرفتم به آبجکتمون که حالا میتونست یه لیست باشه اضافه کنم و برش گردونم و خب باتوجه به اینکه نمیدونیم با چه حجم دیتایی رو به رو هستیم ممکنه 100,000 رکورد باشه این روش زمان زیادی میگیره و طبیعتا Performance مون رو هم میتونه خراب کنه.خب توضیح بسه بریم کد رو اجرا کنیم ببینیم مشکل از کجاست :همونطور که میبینیم وقتی دیباگر از GetData رد میشه نمیره داخل متود ! ، دلیلشم اینه که متود از نوع IEnumerable  هستش و این نوع دیتای سمت سرورمونه و هنوز داخل حافظه ریخته نشده متود زمانی اصطلاحا هیت میشه که ما بخوایم دیتا رو واکشی کنیم و یا عملیات دیگه ایی رو انجام بدیم همونطور که بعدش میبینید زمانی که ما میخوایم Count اش رو بگیریم دیباگر میره داخل متودمون و 6 تا آیتم رو از فایل برامون میخونه بعد زمانی که وارد حلقه foreach  میشه انتظار داریم که مقدار cars پر شده باشه و راحت پیمایشمون اتفاق بیوفته ولی میبینیم که دوباره دیباگر میره توی متود و مجددا دیتار رو میخونه و توی رم میریزه ، به ازای هر تعداد بار دیگه ایی که ما از cars استفاده کنیم یک بار داخل متود رفته و اون رو اجرا میکنه این دقیقا خود مشکلمونه چون اگر تعداد رکورد هامون زیاد باشه این اتفاق Performance مون رو میترکونه.حالا راه حل این مشکل چیه ؟ اینه که دیتا رو همون ابتدا که تابع رو صدا میکنیم داخل لیست بریزیم.GetData.ToList()البته خیلی بهتره زمانی اینکار رو انجام بدیم که مطمئن هستیم دیتامون وجود داره و قرار نیست متودمون نال برگردونه و یا حتی مقدار نال بودن رو چک کنیم تا از Runtime - Error  جلوگیری کرده باشیم (ArgumentNullException)یکبار کدمون رو به این شکل اجرا میکنیم : میبینیم که دیباگر دیگه زمانی که به حلقه foreach میرسیم نمیره سراغ متودمون و متغییر cars مقدار داره همین نکته ی کوچیک میتونه ما رو در استفاده از IEnumerable وارد چالش بکنه .بهتره که زمانی که صرفا میخوایم دیتا رو بخونیم و پاس بدیم به یک سرویس دیگه از IEnumerable استفاده کنیم اگر قراره رو مپ انجام بدیم و یا بیش از یکبار صداش کنیم قطعا باید دنبال جایگزین های بهتری بگردیمشاید الان با خودتون بگید که خب این IEnumerable لعنتی به چه دردی میخوره پس ؟!باید عرض کنم که IEnumerable به دلیل ماهیت Deferred Execution موارد استفاده ی خاصی برای خودش داره به طور مثال زمانی دیتا سورس ما به صورت Concurrent در حال تغییره  ، تعریف متود GetData ما به صورت IEnumerable نه تنها بد نیست بلکه دقیقا درست تعریف شده . این ویژگی Deferred Execution کمک میکنه که شما دقیقا موقع پیمایش متود به آخرین مقدار آپدیت شده دسترسی داشته باشید (منظور این است که از زمانی که شما دیتا رو داخل رم میریزید تا زمان استفاده از اون دیتا منقضی نمیشه) در این حالت نه تنها باید بروز مشکل در Performance ما نمیشه بلکه از نوشتن متود های بیهوده دیگه برای Validate  کردن دیتامون جلوگیری میکنه.یه نکته مهم که خیلی ها شاید بهش توجه نکنن ، شما زمانی که دارید ولیدیشن انجام میدید یا حتی منطقی رو پیاده میکنید هم بهتره IEnumerable  تون رو ToList() کنید چون دقیقا همین اتفاق میوفته شما وقتی یک IEnumerable رو Select میکنید با لینک دقیقا همون پیمایشه داره اتفاق میوفته و خب طبیعتا Performanceمون رو هم خراب میکنه ممنونم از همکار خوب و خفنم پویا شاکری عزیز بابت یادآوری این موضوع بهم.پس میتونیم بگیم شکل نیاز ما در شرایط مختلف میتونه کارایی یک ویژگی رو باز تعریف بکنه به عبارت دیگه نمیتونیم استفاده از IEnumerable رو مضر برای Performance بدانیم فقط باید به جا و بهینه ازش استفاده بشه </description>
                <category>عرشیا دنیابین</category>
                <author>عرشیا دنیابین</author>
                <pubDate>Mon, 06 Mar 2023 16:57:42 +0330</pubDate>
            </item>
                    <item>
                <title>Immutable &amp; Mutable in C#</title>
                <link>https://virgool.io/@arshiadonyabin/mutableandimmutabletypes-upeqjeio9o1i</link>
                <description>کلمات انگلیسی Mutable و Immutable به ترتیب به معنی تغییر پذیر و تغییر ناپذیر هستن توی زبان برنامه نویسی سی شارپ هم همین مفهوم رو دارن این یعنی انواع قابل تغییر آنهایی هستند که مقدار داده آنها پس از ایجاد نمونه قابل تغییر است اما انواع غیرقابل تغییر آنهایی هستند که مقدار داده آنها پس از ایجاد نمونه قابل تغییر نیستند. وقتی مقدار اشیاء قابل تغییر را تغییر می دهیم، مقدار در همان حافظه تغییر می کند. اما در نوع تغییرناپذیر، حافظه جدید ایجاد می شود و مقدار اصلاح شده در حافظه جدید ذخیره می شود.به طور مثال رشته ها Immutable هستند، به این معنی که ما هر بار به جای تغییر بر روی حافظه موجود، حافظه جدیدی تخصیص میدیم بهشون. به عبارت دیگه هر زمان که مقداری از رشته موجود را تغییر می‌دهیم، یعنی یک خونه جدید از حافظه رو بهش اختصاص میدیم که به آن رشته تغییر یافته اشاره می‌کند و مورد قبلی اصطلاحا Dereference می‌شود. (اگر این بخش رو متوجه نشدید پیشنهاد میکنم به این لینک مراجعه کنید)خب اوکی ‍! یه خونه جدید اختصاص بده چی میشه مگه ؟ عرض کنم خدمت حضور انورتون که اگر شما به طور مداوم مقدار یک رشته رو تغییر بدید تعداد خونه های Dereferenced توی حافظه زیاد میشن و همینطوری منتظر Garbage collector میمونن تا بره سراغشون و اون خونه هارو آزاد(Dispose) کنه  و خب این برامون Performance issue  ایجاد میکنه که خب این بده :)string str = string.Empty;
 for (int i = 0; i &lt; 1000; i++)
 {    
   str += &amp;quotAllocated&amp;quot
 }الان توی تکه کد باکس بالا دقیقا اون اتفاقی که توضیح دادم افتاده. به طور کلی ایده جالبی نیست انجام این کاربرای همین در سی شارپ  کلاس StringBuilder رو داریم که از نوع Mutable  هستش اینگونه بنویسیم بهتره :)StringBuilder strB = new StringBuilder(); 
for (int i = 0; i &lt; 10000; i++) 
{
    strB.Append(&amp;quotModified&amp;quot);
}کلاس StringBuilder متود های دیگه ایی مثل Remove , Insert ,Replace  و .. دارد که اگر براتون جذابه میتونید توی وبسایت مایکروسافت بیشتر راجع بهش بخونید.تست سرعت هر دو نمونه کداستفاده شده از پکیج BenchmarkDotNetمزیتی که استفاده از نوع  Immutable بهمون میده  :   Thread safety :اشیاء Immutable از آنجایی که State شی تغییر نمی‌کنه، Thread Safety میشوند ، بنابراین مهم نیست که چند رشته از آن به طور همزمان استفاده کنن، State آن تغییر نمیکند. اگر هر رشته ای به شی با State تغییر یافته نیاز داشته باشه، باید یک شی جدید ایجاد کنه. بنابراین دیگه synchronization issue. وجود نداره. در نتیجه ، تغییرناپذیری Thread safety را تضمین می کند.No State Invalidation : وقتی State یک شیء Immutable را تعریف وکردیم ، هیچ راهی وجود نداره که بدون اطلاع شما توسط هیچ رشته یا فرآیند پس زمینه تغییر کنه. به این ترتیب برنامه هایی که دارای اشیاء تغییرناپذیر هستن از امنیت بالایی برخوردارن.  چون میدونیم که اشیاء شما قبل از وارد شدن به Invalid State ایمن می مانند.Better Encapsulation : کپسوله سازی بخش اساسی برنامه نویسی شی گراست. بدوناون OOP بی معنیه. با کمک اشیاء تغییرناپذیر می تونیم در حین پاس دادن مقدار به روش های مختلف  کپسولاسیون بهتری داشته باشیم و مطمئن باشیم که حالت آنها تغییر نمیکند.Easy Debugging : هر زمان که هنگا خطایی رخ دهد، می دانیم که اشیاء Immutable تغییر نخواهند کرد. به همین خطر اونها نمیتونن عامل ایجاد شدن باگ باشند. بنابراین، در حین debug ، از کدی که دارای یک شی غیرقابل تغییر هست صرف‌نظر میکنیم و debugمون ساده و سریع میشه.Testable Code :تست یک Code Base  با اشیاءImmutable ساده تره چون کد شما دارای Side Effect کمتریه که به طور خودکار منجر به مسیرهای گیج کننده(confusing code) کمتری میشه که در نهایت بررسیشون ساده تره.حالا معایبی که Immutable ها برامون به ارمغان میارن :به نظر من این نوع کنار خوبیای که داره یه بدی بیشتر نداره اونم ابتدای مقاله توضیح دادم با استفاده از این نوع شما از حافظه استفاده بیشتری میکنید و به عبارتی زحمت بیشتری به garbage collector  سی شارپ میدین.درسته که اشیاء immutable مزایای زیادی دارند و همیشه بهتره از اونا استفاده کنید ، اما اشیای Mutable نیز برای دلیلی وجود دارند :  :) Easy To Change :وقتی که از اشیاء  Mutable استفاده می کنیم میتونیم  State اونا رو به طور مکرر تغییر دهیم بدون اینکه آنها را دوباره تعریف کنیم.Memory efficient :استفاده از اشیاء Mutable  روش خوبی برای مدیریت حافظه است چونکه هر زمان که به یک شی با State تغییر یافته نیاز داشتیم نیازی به ایجاد یک شی جدید نیست همونو عوضش میکنیم‌.حالا بدیای این دوستِ Mutable  مون چیه ؟ : تا اینجای کار احتمالا متوجه شدید که تا وقتی immutable ها هستن و میتونیم ازشون استفاده کنیم نریم سراغ Mutable ها بهتره که خب این یه سری دلایل داره که خب نوشتم براتون No Thread Safety : اون بحث که Immutable ها  synchronization issue ندارن رو یادتونه ؟همونطور که برای Immutable ها مزیت بود اینجا بین Mutable ها عیب محسوب میشه به طوری که  state داخلی اشیاء Mutable می تواند توسط هر رشته ای که به آن دسترسی پیدا کند تغییر کند. خب این باعث synchronization issue میشه چون با تعاریفی که داشتیم هیچ دو رشته ای نمی تونن به طور همزمان بهش دسترسی داشته باشن.Reduced Maintainability :وقتی که از اشیاء Mutable استفاده می کنید، نگهداری کد شما دشوار می شود زیرا State اشیاء شما در سرتاسر کد تغییر می کند و توان عملیاتی را کاهش می دهد.Difficult to debug and test : اشیاء Mutable  تست و Debug کد شما را دشوار می کنند زیرا مسیرهای کد بیشتر منجر به سردرگمی می شود. Debug نیز دشوار است زیرا State شیء به طور مکرر تغییر می کند.بقیش بمونه مقاله بعدی ، باشد که رستگار شویم‌:))</description>
                <category>عرشیا دنیابین</category>
                <author>عرشیا دنیابین</author>
                <pubDate>Tue, 20 Sep 2022 21:54:26 +0430</pubDate>
            </item>
                    <item>
                <title>چرا باید مفاهیم S.O.L.I.D. رو یاد بگیریم؟</title>
                <link>https://virgool.io/@arshiadonyabin/whyweshouldlearnsolid-dtvtfpx3wfy6</link>
                <description>آقاا خیلی وقتا من شنیدم که برنامه نویس های تازه کار و یا حتی برنامه نویسای با تجربه تر  نسبت به این اصول جبهه دارن یا با design pattern  ها قاطیش میکنن یا حتی جدیشن نمیگیرن گفتم یه چند خط بنویسم براتون که اصلا داستان چیه ؟ پنج اصل SOLID توسط Robert C. Martin معروف به (Uncle Bob) برای اولین بار مطرح شد.هدف از SOLID توسعه کدهای با خوانایی بالاتر و توسعه پذیر تر و همچنین ایجاد یک استاندارد بین تمامی توسعه دهندگان است.استفاده از اصول سالید از به وجود آمدن مشکلاتی نظیر : Duplication ، Viscosity ، Immobility، Fragility و ...  جلوگیری میکندتفاوت این دو مفهوم اینه که الگوهای طراحی یا design pattern ها ، مجموعه ای از کدها و راه حل‌های از پیش نوشته شده هستند که هر کدام مشکلی رو حل می کنند، یعنی در شرایط خاص از الگوهای طراحی برای حل مشکل استفاده کرد. اما، SOLID قوانینی هستند که برای نوشتن کدها استفاده میشوند , و یا به عبارت دیگه حین توسعه نرم افزار اگر از این قوانین استفاده کنیم در آینده موقع نگه داری محصولمون خیلی راحت تریم :) حالا به جز نگه داری پروژمون scalable و  testable هم میشه( اگر اونقدری کارکرد نرم افزارمون برامون مهمه و بخوایم بدون باگ باشه و بخوایم از روش درستیابی فرمال استفاده کنیم خیلی کمکمون میکنه وقتی این اصول و رعایت کرده باشیم)سوالی که این وسط برای همه پیش میاد اینه که میگن من مفاهیم شی گرایی رو بلدم و دیگه نیازی به قواعد S.O.L.I.D. ندارم که یاد بگیرم. بذارید این دو مسئله رو از هم جدا کنیم. اگه بخوام یه مثال ساده بزنم، برای یادگیری و استفاده از هر دو مسئله اینه که شما تمام ابزارهای چوب بری رو در اختیار داشته باشی و بگی که خب نیازی نیست که علم چوب بری هم یاد بگیرم.با یادگیری برنامه نویسی شئ گرا، در حقیقت یاد میگیرد که چطوری از کلاس ها استفاده کنید ، چگونه برای یک کلاس خصوصیت تعریف کنیم  و به طور کلی یه دید انتزاعی نسبت به اشیا و موجودیت هامون پیدا میکنیم  ، اما اینکه بتونیم از این قابلیت‌ها در مسیر درست استفاده کنیم داستان فرق میکنه.S.O.L.I.D. در واقع یک چهارچوب منظم رو برای ما ایجاد میکنه که مکمل شی گرایی است و با حرکت در این مسیر میتوانیم کدهای بهینه تری بنویسیم.SOLID مخفف پنج عبارته زیر است:سعی میکنم یه توضیح مختصر راجع به هر کدوم بدم ، اگه در آینده حالشو داشتم هر کدوم رو میشکافم و با نمونه کد تو یه مقاله دیگه بررسیش میکنم فعلا خستم :)1) S: Single Responsibility Principleهر بخش از نرم افزار حالا کلاس ، تابع یا حتی یه کامپوننت وظیفه انجام تنها و تنها یک کار را دارد هیچ یک نباید دو یا چند عملیات انجام دهد.یا به عبارت دیگه هر بخش از نرم افزارمون وظیفه هندل کردن یک نگرانی رو داشته باشه (اگر این جمله رو متوجه نمیشید بهتره که راجع به مفهوم Seperation of concern تحقیق کنید)2) O: Open/Closed Principleهر کلاسی باید برای توسعه یافتن قابلیت‌هایش اصطلاحاً Open بوده و دست برنامه‌نویس برای افزودن فیچرهای جدید به آن باز باشد اما اگر وی خواست تا تغییری در کلاس ایجاد کند، چنین امکان باید Closed بوده و او اجازهٔ چنین کاری را نداشته باشد.ضمانت می‌کند که کلاس ها قابل ارث بری و استفاده هستند ولی نباید از بیرون قابل تغییر باشند.3) L: Liskov Substitution Principleاین دوستمون میگه که  که کلاس‌های فرزند باید آن‌قدر کامل و جامع از کلاس والد خود ارث‌بری کرده باشند که به سادگی بتوان همان رفتاری که با کلاس والد می‌کنیم را با کلاس‌های فرزند هم داشته باشیم به طوری که اگر در شرایطی قرار گرفتید که با خود گفتید کلاس فرزند می‌تواند تمامی کارهای کلاس والدش را انجام دهد به جزء برخی موارد خاص، اینجا است که این اصل رو خیلی زیبا نقض کردید :)4) I: Interface Segregation Principleاینترفیس‌ها فقط مشخص می‌کنند که یک کلاس از چه متدهایی حتماً باید برخوردار باشد. در همین راستا و بر اساس این قانون، چندین اینترفیس تک‌منظوره به مراتب بهتر است از یک اینترفیس چندمنظوره است به طوری که اگر یک اینترفیس چندمنظورهٔ کامل و جامع داشته باشیم و سایر کلاس‌های ما از آن اصطلاحاً implements کنند،‌ در چنین صورتی ممکن است برخی خصوصیات، متدها و رفتارها را به برخی کلاس‌هایی که اصلاً نیازی به آن‌ها ندارند تحمیل کنیم و خب این بده ! ،  اما اگر از چندین اینترفیس تخصصی استفاده کنیم، به سادگی می‌توانیم از هر اینترفیسی که نیاز داشته باشیم در کلاس‌های مد نظر خود استفاده نماییم و در صورتی هم کلاسی وجود داشت که نیاز به استفاده از چندین اینترفیس مختلف داشت، دست ما باز خواهد بود تا آن کلاس را از چندین اینترفیس implements کنیم.5) D: Dependency Inversion Principleاین آخرین اصل سالیده و از نظر من غول مرحله آخرم میشه اسمشو گذاشت.. XD اول بگم که این غول مرحله آخر رو با Dependency injection قاطی نکنید فرق دارن درک این دوستمون یکم سخته..  به طور خلاصه، در OOP باید تمام تلاش خود را به کار بندیم تا Dependency (وابستگی) را مابین کلاس‌ها، ماژول‌ها و آبجکت‌های سطح بالا با ماژول‌های سطح پایین به حداقل برسانیم که با این کار، اِعمال تغییرات در آینده به مراتب راحت‌تر صورت خواهد پذیرفت :) ما باید این وابستگی هارو معکوس کنیم یعنی ماژول‌های سطح بالا نباید به ماژول‌های سطح پایین وابسته باشند. هر دوی آن‌ها (ماژول‌های سطح بالا و پایین) باید به Abstraction‌ ها وابسته باشند و باز هم به زبان ساده تر : Abstraction‌ ها نباید به جزئیات وابسته باشند. جزئیات باید به Abstraction‌ ها وابسته باشند.</description>
                <category>عرشیا دنیابین</category>
                <author>عرشیا دنیابین</author>
                <pubDate>Fri, 06 May 2022 18:42:24 +0430</pubDate>
            </item>
                    <item>
                <title>تفاوت ValueType &amp; RefrenceType</title>
                <link>https://virgool.io/@arshiadonyabin/diffrencebetweenvaluetypeandrefrencetype-hae0qbfqvkmw</link>
                <description>طبق انواع DataType های زبان C# دو تا از مهمترین اونا Value type ها و Reference typeها هستند که با نحوه ذخیره سازی در حافظه تفاوت پیدا میکنند. به طوری که Value Typeها در Stack ذخیره میشوند ولی Reference Typeها در Stack و Heap  اما یعنی چی؟بذارید یه چیزی رو تعریف کنم، رفته بودم برای مصاحبه و ازم پرسیدند که فرق بین Value type و Reference type در زبان C# چیه منم که جمله بالا رو خوب تو ذهنم بود سریع گفتم و با مثال زدن Struct و Class تفاوت هارو گفتم ولی در عمل ازم خواستند تا مثالی رو حل کنم ولی خب نتونستم جواب بدم. خیلی برام جالب شد و رفتم اساسی راجع بهش خوندم و به نتایجی رسیدم که دیدم حیفه اینجا به اشتراک نذارم.1) Value Type:این نوع متغیرها مقدار خودشون رو به همراه فضای حافظه ذخیره میکنند. یعنی متغیر به صورت مستقیم و بدون واسطه مقدارش رو حفظ کرده.مثلا این متغیر Integer:int i = 100;سیستم مقدار 100 رو در حافظه رو دقیقن با i ذخیره میکنه، عکس پایین نشون میده که مثلا خونه حافظه 0x239110 به طور فرضی اختصاص پیدا کرده به متغیر i:انواع Value type ها:boolbytechardecimaldoubleenumfloatintlongsbyteshortstructuintulongushortمقدار دهی کردن Value type ها:وقتی که مقدار یک متغیر Value Type رو به یک متد دیگر پاس میدهیم، در سیستم یه نسخه جدا از متغیر در اون متد خاص ساخته میشه. بنابراین اگر مقدار در اون متد خاص متغیر تغییر کنه تاثیری روی مقدار متغیر در متد دیگه ای نخواهد داشت، مثال زیر رو ببینید:static void ChangeValue(int x){    x =  200;    Console.WriteLine(x);}static void Main(string[] args){    int i = 100;    Console.WriteLine(i);     ChangeValue(i);     Console.WriteLine(i);}خروجی:100 
200 
100همانطور که میبینید متغیر i در متد Main مقدارش تغییری نکرد حتی بعد از اینکه ما مقدارش رو پاس دادیم به متد ChangeValue و در اون متد تغییرش دادیم.2) Reference Type:خب برخلافه Value Type ها که توضیح دادیم، Reference Type ها مقدار رو مستقیم در خودشون ذخیره نمیکنند. به جاش آدرس خونه حافظه ای که در اونجا، مقدار ذخیره شده، رو نگه میدارند. بذار یه جور دیگه بگیم اگه بحث اشاره‌گرها در زبان C رو یادتون باشه، در واقع یک Reference Type یه اشاره گری در خودش داره که این اشاره گر حاوی آدرس خونه ای از حافظه‌س که مقدار در اون نگه داری شده.اینجا رشته ها از جنس RefrenceType  ها هستند مقال رو ببینید : string s = &quot;Hello World!!&quot;;اینجا چه اتفاقی میوفته، در واقع سیستم مقدار نسبت داده شده رو در یک خانه حافظه ذخیره میکنه و بعد یک خونه حافظه رو اختصاص میده به اسم متغیر و در اون آدرس مقدار متغیر رو نگه میداره، عکس زیر رو ببینید:همانطوری که دیدید، سیستم به صورت کاملن اتقاقی خانه‌ای رو برای ذخیره مقدار انتخاب میکنه و بعد یک خانه دیگر حافظه رو با اسم متغیر و  آدرس خانه‌ی مقدار آن ، نسبت میده . بدین ترتیب همونطوری هم که از اسم این نوع متغیر پیداست به جای ذخیره سازی مستقیم مقدار آدرس حافظه درش نگه داری میشه.انواع Reference type ها:Stringهمه arrayها, حتی وقتی عناصر تشکلیل دهندشون value type باشندClassDelegatesمقدار دهی کردن Reference type ها:تفاوت اصلی اینجا معلوم میشه چون وقتی که یک Reference type رو از یک متد به متد دیگه‌ای پاس میدیم دیگه یه نسخه جدید ازش ساخته نمیشه، به جاش آدرس خونه حافظه اختصاص یافته به متغیر پاس میشه. اگر ما در متد خودمون تغییری روی مقادیر کلاس ایجاد کنیم در همه جا تغییر خواهد کرد.static void ChangeReferenceType(Student std2)
{
    std2.StudentName = &amp;quotSteve&amp;quot
}

static void Main(string[] args)
{
    Student std1 = new Student();
    std1.StudentName = &amp;quotBill&amp;quot
    
    ChangeReferenceType(std1);

    Console.WriteLine(std1.StudentName);
}خروجی:Steveدر مثالی که دیدید، زمانی که ما یک نسخه از Student رو با نام std1 به متد ChangeReferenceType میفرستیم، اتفاقی که میوفته اینه که آدرس خانه حافظه std1 ارسال میشه. بدین ترتیب وقتی که متد StudentName رو تغییر میده در کلاس اصلی ما هم نام تغییر میکنه. چرا؟ چون std1 و std2 دارند هر دو به یک خونه حافظه اشاره میکنند و یه جورایی میشه گفت هردوشون یکی هستند. بنابراین خروجی ما Steve خواهد بود.null value:Reference type ها یکی از خاصیتهایی که دارند اینه که اگه شما به اونهارو مقدار دهی نکنید به صورت پیش فرض مقدار Null یا تهی دارند. بذارید یه مثال بزنم، یک متغیر از جنس رشته یا string (میتونه هر نوع دیگه‌ای از Reference Typeها باشه) وقتی که مقدار دهی نشه مقدار Null درش قرار میگیره که این به معنیه که دیگه به هیچ خونه ای از حافظه اشاره نمیکنه و آدرسی نداره، چون هنوز قرار نیست مقداری داشته باشه.اما Value type ها نمیتونن Null باشند چون مقدار رو در خودشون نگه میدارند نه آدرس خونه حافظه رو. بنابراین قبل از استفاده از Value typeها باید حتما مقدار دهی شده باشند. اگه تکه کد زیر رو امتحان کنید خود Compiler بهتون خطا میده و بهتون میگه متغیری که تعریف کرده‌اید رو نمیتونید استفاده کنید تا زمانی که یک مقدار به آن نسبت بدید.void someFunction()
{
    int i;

    Console.WriteLine(i);یه چیز جالب دیگه اینکه، Value type هایی که به صورت یک Property در کلاس تعریف میشوند (نه به صورت محلی در تابع جاری)، زمانی که اونارو مقدار دهی نکنیم، مقدار پیش فرض رو به صورت اتوماتیک دریافت میکنند. مثلا متغیر از جنس integer مقدار 0 و یا boolean مقدار False رو به خودش اختصاص میده. مثال رو ببینید:class myClass
{
    public int i;
}

myClass mcls = new myClass();

Console.WriteLine(mcls.i);خروجی:0مقدار پیش فرض متغیرهای دیگه رو میتونید در سایت خود ماکروسافت ببینید.یک نکته رو بگم که از C# 2.0 به بعد nullable typeها برای Value typeها معرفی شدند که میشه مقداری رو بهشون نسبت نداد، ولی خب این متغیرها قطعن دیگه از نوع مستقیم Value type نیستند.نکاتی که باید یادمون بمونه:1) Value typeها مقدار رو به همراه نام متغیر در خانه حافظه نگه داری میکنند در صورتی که Reference type ها فقط آدرس خونه ای از حافظه رو که مقدار اصلی در آنجاست را نگهداری میکنند.2) تمامی داده های عددی و Structها Value type و class، string، array و delegate ها از نوع Reference type هستند.3) Value type ها با به صورت پیش فرض با مقدار جابه‌جا میشن ولی Reference Typeها با آدرس.4) در حافظه، Value type ها در Stack و Reference type ها با توجه به اندازه متغیر در Stack و Heap ذخیره میشوند.من این نوشته رو از وبلاگ همکار خوبم Amin Mohammadi خوندم و برام جذاب بود تا توی ویرگولم منتشر کنم.</description>
                <category>عرشیا دنیابین</category>
                <author>عرشیا دنیابین</author>
                <pubDate>Tue, 03 May 2022 00:47:05 +0430</pubDate>
            </item>
            </channel>
</rss>