C# Geeks (.NET) – Telegram
🚧 خطای IndexOutOfRangeException :
چرا آرایه‌ها از لبه پرت می‌شوند؟
یکی از اولین و رایج‌ترین خطاهای زمان اجرایی که هر برنامه‌نویس #C باهاش روبرو میشه، همین IndexOutOfRangeException هست. اون لحظه‌ای که فکر می‌کنی همه چی درسته، ولی برنامه با این خطا کرش می‌کنه.

اما این خطا دشمن شما نیست، بلکه یه نگهبان مهمه! بیاید ببینیم داستانش چیه و چرا وجودش برای ما خوبه.

1️⃣ بررسی محدوده (Bounds Checking) چیست؟

وقتی شما یک آرایه می‌سازید، در واقع یک محدوده مشخص در حافظه تعریف می‌کنید. Bounds Checking یعنی CLR (محیط اجرای دات‌نت)، قبل از دسترسی به هر خانه‌ی آرایه، مثل یه نگهبان با دقت چک می‌کنه که آیا ایندکسی که دادی، تو محدوده مجاز آرایه هست یا نه.

اگه از محدوده خارج بزنید، اون نگهبان جلوتون رو می‌گیره و خطای IndexOutOfRangeException رو پرتاب می‌کنه.
// آرایه‌ای با ۳ عنصر که ایندکس‌های مجاز آن 0, 1, 2 هستند
int[] arr = new int[3];

arr[0] = 10; // مجاز
arr[2] = 30; // مجاز

// تلاش برای دسترسی به ایندکس 3 که وجود نداره!
arr[3] = 40; // 💥 BOOM! IndexOutOfRangeException


2️⃣چرا این خطا یک "ویژگی" خوب است؟

شاید اولش از این خطا بدتون بیاد، ولی وجودش دو تا دلیل خیلی مهم داره:

امنیت و پایداری (Safety) :

این بررسی جلوی دسترسی و تخریب ناخواسته بخش‌های دیگه حافظه رو می‌گیره. اگه این خطا نبود، ممکن بود برنامه‌تون داده‌های دیگه رو خراب کنه و هیچوقت نفهمید مشکل از کجاست.

دیباگ آسان :

به جای اینکه برنامه‌تون با یه رفتار عجیب و غریب به کارش ادامه بده و بعداً یه جای نامربوط کرش کنه، دقیقاً همون لحظه و همون خطی که اشتباه کردی، بهت خطا میده. این دیباگ کردن رو فوق‌العاده راحت‌تر می‌کنه.

3️⃣آیا این بررسی روی پرفورمنس تأثیر دارد؟ 🚀

شاید فکر کنید این همه چک کردن، برنامه رو کند می‌کنه. درسته که یه هزینه خیلی جزئی داره، ولی کامپایلر JIT (Just-In-Time) خیلی هوشمنده.

مثلاً، قبل از ورود به یه حلقه، اگه بفهمه تمام ایندکس‌ها امن هستن، چک کردن رو برای کل حلقه بهینه می‌کنه. پس در ۹۹٪ مواقع، تأثیر این بررسی روی پرفورمنس ناچیز و قابل چشم‌پوشی است.

نکته حرفه‌ای: البته #C به شما اجازه میده در شرایط خاص و با مسئولیت خودتان، با استفاده از کد unsafe این بررسی امنیتی رو دور بزنید، که یه بحث خیلی پیشرفته‌ست.
🤔 حرف حساب و خاطرات شما
پس دفعه بعدی که این خطا رو دیدید، بهش به چشم یه دشمن نگاه نکنید، بلکه ازش به عنوان یه راهنما که داره اشتباهتون رو دقیق نشون میده، تشکر کنید!

اولین باری که به این خطا برخوردید یادتونه؟ داشتید روی چه کدی کار می‌کردید؟ بیاید از خاطرات مشترک برنامه‌نویسیمون بگیم!

ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.
[@CSharpGeeksChat]

🔖 هشتگ‌ها :
#CSharp
#ErrorHandling
#DotNet
#Exception
🧠 کالبدشکافی حافظه در C# Stack در برابر Heap


وقتی یه متغیر تعریف می‌کنید، دقیقاً کجا میره؟ چرا بعضی متغیرها بلافاصله بعد از خروج از متد از بین میرن ولی بعضی دیگه باقی می‌مونن؟

جواب این سوال‌ها تو دو تا از مهم‌ترین مفاهیم کامپیوتر نهفته‌ست: Stack (پشته) و Heap (هیپ). درک این دو، شما رو از یه کدنویس ساده به یه توسعه‌دهنده واقعی تبدیل می‌کنه.

1️⃣پشته (Stack) :

حافظه‌ی سریع و منظم فکر کنید Stack مثل یه دسته بشقابه که روی هم چیدید. آخرین بشقابی که میذارید، اولین بشقابیه که برمیدارید (LIFO: Last-In, First-Out).

چی توش ذخیره میشه؟ این بخش از حافظه برای ذخیره‌ی متغیرهای محلی و پارامترهای متدها استفاده میشه. بیشتر Value Type ها اینجا زندگی می‌کنن.

چطور کار می‌کنه؟ با هر بار صدا زدن یک متد، حافظه مورد نیاز اون متد بالای پشته قرار می‌گیره و با تمام شدن متد، اون بخش از حافظه بلافاصله آزاد میشه. این کار فوق‌العاده سریعه.

static int Factorial (int x) 
{
if (x == 0) return 1;
return x * Factorial (x - 1);
}

هر بار که Factorial خودشو صدا می‌زنه، یه int x جدید روی پشته ساخته میشه و با برگشتن جواب، اون int از روی پشته برداشته میشه.

2️⃣هیپ (Heap) :

هیپ مثل یه انبار بزرگه. هر وقت یه آبجکت جدید می‌سازید (new)، CLR یه جای خالی تو این انبار پیدا می‌کنه، آبجکت رو اونجا میذاره و یه "آدرس" یا "رفرنس" به شما برمی‌گردونه.

چی توش ذخیره میشه؟ تمام آبجکت‌ها (نمونه‌های Reference Type) اینجا زندگی می‌کنن.

چطور کار می‌کنه؟ این حافظه توسط یه رفتگر هوشمند به اسم Garbage Collector (GC) مدیریت میشه. GC هر چند وقت یکبار میاد و آبجکت‌هایی که دیگه هیچ رفرنسی بهشون اشاره نمی‌کنه (آبجکت‌های یتیم) رو از حافظه پاک می‌کنه تا فضا آزاد بشه.

StringBuilder ref1 = new StringBuilder("obj1");
Console.WriteLine(ref1);
// بعد از این خط، دیگه هیچ رفرنسی به آبجکت "obj1" اشاره نمی‌کنه
// و آماده پاک شدن توسط GC میشه.

StringBuilder ref2 = new StringBuilder("obj2");
StringBuilder ref3 = ref2;
// اینجا با اینکه ref2 دیگه استفاده نمیشه، چون ref3 هنوز به "obj2"
// اشاره می‌کنه، این آبجکت زنده می‌مونه!
Console.WriteLine(ref3);


نکته: فیلدهای استاتیک هم روی هیپ ذخیره میشن، ولی تا پایان عمر برنامه زنده می‌مونن.

🤔 پس Value Typeها دقیقاً کجا زندگی می‌کنند؟
این سوال مهمیه! قانونش اینه: Value Typeها هرجا که تعریف بشن، همونجا زندگی می‌کنن.

اگه به عنوان یه متغیر محلی تو یه متد تعریف بشن ⟵ روی Stack.

اگه به عنوان یه فیلد داخل یه کلاس (که خودش یه Reference Type هست) تعریف بشن ⟵ همراه با اون آبجکت روی Heap!

حرف حساب و درک عمیق‌تر
درک تفاوت Stack و Heap فقط یه بحث تئوری نیست؛ روی پرفورمنس، مدیریت حافظه و حتی نحوه طراحی کلاس‌های شما تأثیر مستقیم داره.

این توضیح چقدر به درک بهتر شما از رفتار Value Type و Reference Type کمک کرد؟ آیا نکته‌ای در مورد Stack و Heap بود که براتون تازگی داشته باشه؟

نظراتتون رو کامنت کنید! 👇
[پاتوق گیک های #C]

🔖 هشتگ‌ها :
#CSharp
#MemoryManagement
#DotNet #Stack #Heap
🛡 سیاست تخصیص قطعی در #C: چرا کامپایلر از شما باهوش‌تر است؟
تا حالا براتون سوال شده چرا گاهی اوقات اگه به یه متغیر مقدار اولیه ندید، کامپایلر ازتون ایراد میگیره، ولی گاهی اوقات خودش بهش مقدار صفر یا null میده؟

این رفتار شانسی نیست! پشتش یه قانون مهم و امنیتی در #C به اسم "سیاست تخصیص قطعی" (Definite Assignment) خوابیده. این قانون میگه شما هرگز نمی‌تونید به حافظه‌ای که مقداردهی اولیه نشده، دسترسی داشته باشید.

1️⃣قانون برای متغیرهای محلی: خودت باید مقدار بدی!
وقتی یه متغیر داخل یک متد تعریف می‌کنی (Local Variable)، #C به تو اعتماد می‌کنه و وظیفه مقداردهی اولیه رو به عهده خودت میذاره. اگر قبل از اینکه مقداری بهش بدی، سعی کنی ازش استفاده کنی (بخونیش)، کامپایلر جلوت رو می‌گیره و خطای زمان کامپایل (Compile-time error) میده.
void MyMethod()
{
int x;

// خطای زمان کامپایل!
// کامپایلر میگه: "تو به من نگفتی تو x چی بریزم!"
Console.WriteLine(x);
}

2️⃣قانون برای فیلدها و آرایه‌ها: همیشه مقدار دارند!
اما برای اعضایی که طول عمر بیشتری دارن، مثل فیلدهای یک کلاس (چه static و چه instance) یا عناصر یک آرایه، داستان فرق می‌کنه.

اینجا NET runtime. برای جلوگیری از مشکلات، همیشه اون‌ها رو به صورت خودکار با مقدار پیش‌فرضِ نوع داده‌شون مقداردهی می‌کنه.
// آرایه‌ها همیشه با مقادیر پیش‌فرض پر میشن (برای int، صفره)
int[] numbers = new int[3];
Console.WriteLine(numbers[0]); // خروجی: 0


class Test
{
// فیلدها هم همیشه مقدار پیش‌فرض میگیرن
public static int X;
}

// ...
Console.WriteLine(Test.X); // خروجی: 0


🤔 چرا این تفاوت وجود دارد؟
این یه تصمیم هوشمندانه برای امنیته. برای متغیرهای محلی، کامپایلر می‌تونه به سادگی و با قاطعیت تشخیص بده که شما فراموش کردید مقداردهی کنید و همونجا جلوتون رو بگیره. اما برای فیلدها و آرایه‌ها که چرخه حیاتشون پیچیده‌تره، مقداردهی خودکار توسط runtime، جلوی باگ‌های خطرناک ناشی از حافظه‌ی مقداردهی نشده رو می‌گیره.

پس این "ایراد گرفتن" کامپایلر، در واقع یه کمک بزرگه!
نظراتتون رو کامنت کنید! 👇
[C# Geeks Hangout]

🔖 هشتگ‌ها :
#CSharp
#Compiler
#DotNet #SoftwareEngineering
🐣 مقادیر پیش‌فرض (Default Values) در #C :
هر متغیر با چه مقداری متولد می‌شود؟
تو پست "سیاست تخصیص قطعی" دیدیم که فیلدهای یک کلاس و عناصر یک آرایه به صورت خودکار مقداردهی اولیه میشن. اما سوال اینجاست: چه مقداری؟ این مقادیر از کجا میان؟

جواب تو یه مفهوم ساده به اسم مقدار پیش‌فرض (Default Value) هست.

مقادیر پیش‌فرض چیست؟ 🔢

هر نوع داده‌ای در #C یک مقدار پیش‌فرض داره که حاصل صفر کردن بیت‌های حافظه (Bitwise Zeroing) هست. این یعنی:

●تمام Reference Typeها (کلاس، string، آرایه، ...): مقدار پیش‌فرضشون null هست.

●تمام Numeric Typeها (int, double, decimal, ...): مقدار پیش‌فرضشون 0 هست.

●نوع bool: مقدار پیش‌فرصش false هست.

●نوع char: مقدار پیش‌فرصش '\0' (کاراکتر نال) هست.

کلمه کلیدی default

سی‌شارپ یه کلمه کلیدی شیک و کاربردی به اسم default در اختیار ما میذاره تا بتونیم مقدار پیش‌فرض هر نوعی رو به راحتی بدست بیاریم، بدون اینکه نیازی به حفظ کردنشون داشته باشیم.

// گرفتن مقدار پیش‌فرض decimal
decimal d1 = default(decimal); // حاصل: 0

// روش مدرن‌تر و خلاصه‌تر
// کامپایلر خودش نوع رو از متغیر تشخیص میده
int i = default; // حاصل: 0
bool b = default; // حاصل: false
string s = default; // حاصل: null


تکلیف structها چیست؟ 🏗

مقدار پیش‌فرض برای یک struct سفارشی، خیلی ساده‌ست: معادل مقدار پیش‌فرض تمام فیلدهای داخل اون struct هست.
public struct Point 
{
public int X; // پیش‌فرض: 0
public string Name; // پیش‌فرض: null
}

Point p = default;

// اینجا p.X برابر 0 و p.Name برابر null خواهد بود
Console.WriteLine($"X: {p.X}, Name: {p.Name ?? "null"}");


🤔 حرف حساب و تجربه شما

دونستن مقادیر پیش‌فرض به شما کمک می‌کنه رفتار اولیه کدهاتون رو بهتر درک کنید و از خطاهای ناشی از مقادیر ناخواسته جلوگیری کنید.

آیا تا حالا از کلمه کلیدی default تو کدهاتون استفاده کردید؟ یا جایی بوده که مقداردهی پیش‌فرض یه فیلد یا آرایه شما رو غافلگیر کرده باشه؟

نظراتتون رو کامنت کنید! 👇
[پاتوق گیک های #C]

🔖 هشتگ‌ها :
#CSharp
#CodingTips
#SoftwareEngineering
📮 پاس دادن پارامترها در #C :

راز بزرگ کپی شدن "مقدار" و "رفرنس"
یکی از بنیادی‌ترین مفاهیمی که هر توسعه‌دهنده #C باید بهش مسلط باشه، نحوه پاس دادن پارامترها به متدهاست.

قانون اصلی اینه: در #C، همه چیز به صورت پیش‌فرض بر اساس مقدار (Pass-by-Value) پاس داده میشه. اما این جمله ساده، برای Value Type و Reference Type دو معنی کاملاً متفاوت داره!

1️⃣سناریو اول: پاس دادن Value Type (کپی کامل)
وقتی یه Value Type (مثل int, struct, bool) رو به یه متد میدید، انگار یه فتوکپی کامل از مقدار اون متغیر می‌گیرید و اون کپی رو به متد میدید.

متد با اون کپی هر کاری بکنه، اصل سند شما دست نخورده باقی می‌مونه.
int x = 8;

// یک کپی از مقدار 8 به متد فرستاده میشه
Foo(x);

// x اینجا هنوز همون 8 باقی مونده!
Console.WriteLine(x); // خروجی: 8

static void Foo(int p)
{
// p فقط یک کپی از x هست و در یک جای جدا در حافظه قرار داره
p = p + 1;
Console.WriteLine(p); // خروجی: 9
}


2️⃣سناریو دوم: پاس دادن Reference Type (کپی کلید!) 🔑
اینجا داستان کاملاً فرق می‌کنه و همونجاییه که خیلی‌ها به اشتباه میفتن.

وقتی یه Reference Type (مثل یه class یا StringBuilder) رو به متد پاس میدید، شما خودِ آبجکت (خونه) رو بهش نمیدید، بلکه یه کپی از کلید (رفرنس) اون خونه رو بهش میدید.

این یعنی حالا دو تا کلید داریم که هر دو، یک در رو باز می‌کنن!

این رفتار دو تا نتیجه مهم داره:

اگه محتوای خونه رو عوض کنیم، برای همه عوض میشه:
متد با کلید کپی شده می‌تونه بره تو همون خونه و دکوراسیون رو عوض کنه. این تغییر روی آبجکت اصلی تأثیر میذاره چون هر دو کلید یه خونه رو باز می‌کنن.

اگه کلید کپی شده رو عوض کنیم، کلید اصلی ما امنه:
ولی اگه متد، خودِ کلید کپی شده رو با یه کلید دیگه عوض کنه (مثلاً fooSB = null)، شما هنوز کلید اصلی خودتون رو دارید و آبجکت اصلی شما null نمیشه.
StringBuilder sb = new StringBuilder("original");

Foo(sb);

// محتوای sb تغییر کرده چون متد، دکوراسیون خونه رو عوض کرد
Console.WriteLine(sb.ToString()); // خروجی: original-test

static void Foo(StringBuilder fooSB)
{
// ۱. با کلید کپی شده، محتوای آبجکت اصلی رو تغییر میدیم
fooSB.Append("-test");

// ۲. خودِ کلید کپی شده رو null می‌کنیم.
// این کار هیچ تأثیری روی متغیر sb اصلی نداره.
fooSB = null;
}


🤔 حرف حساب و تجربه شما

درک این تفاوت، کلید اصلی جلوگیری از باگ‌های غیرمنتظره‌ایه که توش داده‌ها به شکلی که انتظار ندارید، تغییر می‌کنن.

آیا این رفتار برای پاس دادن Reference Typeها براتون کاملاً روشن بود؟ یا تا حالا با مشکلی مواجه شدید که توش یه آبجکت داخل یه متد تغییر کرده و شما رو غافلگیر کرده باشه؟

خب، اینجا که نمیشه همه حرفا رو زد! 😉

ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.

[C# Geeks Hangout]

🔖 هشتگ‌ها :
#CSharp
#Parameters
#ReferenceTypes #ValueTypes
🔄 ابزار حرفه‌ای #C :
تغییر متغیرها از راه دور با ref

تا حالا شده بخوای یه متغیر رو به یه متد پاس بدی و خودِ متد بتونه مقدار اصلی اون متغیر رو تغییر بده؟ به صورت پیش‌فرض این کار ممکن نیست (چون در حالت عادی، فقط یک کپی از مقدار پاس داده میشه).

اما #C یه ابزار قدرتمند برای این کار داره:
کلمه کلیدی ref.

وقتی از ref استفاده می‌کنی، دیگه کپی مقدار رو به متد نمیدی، بلکه خودِ آدرس حافظه متغیر رو بهش میدی. حالا متد و کد اصلی، هر دو به یک خانه از حافظه نگاه می‌کنن و هر تغییری، همه جا اعمال میشه.

قانون مهم: باید از کلمه کلیدی ref هم در تعریف متد و هم موقع صدا زدنش استفاده کنی. این کار باعث میشه کد کاملاً خوانا باشه و همه بفهمن که اینجا قراره متغیر اصلی تغییر کنه.

مثال کلاسیک و بهترین کاربرد ref (متد Swap):
static void Swap(ref string a, ref string b)
{
// چون a و b به متغیرهای اصلی اشاره دارن،
// هر تغییری اینجا، مستقیماً روی x و y تأثیر میذاره.
string temp = a;
a = b;
b = temp;
}

// --- نحوه استفاده ---
string x = "Penn";
string y = "Teller";

// با ref متغیرهای اصلی رو به متد می‌فرستیم
Swap(ref x, ref y);

Console.WriteLine(x); // خروجی: Teller
Console.WriteLine(y); // خروجی: Penn


🤔 حرف حساب و تجربه شما

استفاده از ref برای مواقع خاص و قدرتمندیه و به شما کنترل بیشتری روی حافظه میده.
شما تا حالا کجا از ref استفاده کردید که واقعاً به دردتون خورده باشه؟

ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.
[پاتوق گیک های #C]

🔖 هشتگ‌ها:
#CSharp
#DotNet
#RefKeyword
📤 ابزار حرفه‌ای #C :
بازگرداندن چند مقدار از متد با out

تا حالا شده بخوای یه متد بنویسی که بیشتر از یه مقدار رو برگردونه؟ مثلاً هم نتیجه عملیات و هم یه پیام وضعیت؟ تو #C برای این کار یه ابزار فوق‌العاده داریم:
کلمه کلیدی out.


این کلمه کلیدی به شما اجازه میده پارامترهایی تعریف کنید که مقدارشون از داخل متد به بیرون منتقل میشه.

این out چیست و چه فرقی با ref داره؟

کلمه کلیدی out هم مثل ref، پارامتر رو بر اساس رفرنس پاس میده (یعنی آدرس حافظه رو میفرسته). اما دو تا قانون مهم و متفاوت داره:

1️⃣نیازی نیست قبل از متد مقداردهی بشه: شما می‌تونید یه متغیر تعریف نشده رو به یه پارامتر out پاس بدید.

2️⃣حتماً باید داخل متد مقداردهی بشه: متد موظفه که قبل از تموم شدن، یه مقداری رو تو اون پارامتر بریزه. این قانون توسط کامپایلر چک میشه.

کاربرد اصلی: بازگرداندن چند مقدار
بهترین کاربرد out، زمانیه که می‌خواید از یک متد، چند مقدار خروجی بگیرید.

مثال: فرض کنید می‌خوایم یه متد بنویسیم که اسم کامل رو بگیره و اسم کوچک و فامیل رو جدا کنه.
void Split(string fullName, out string firstName, out string lastName)
{
int i = fullName.LastIndexOf(' ');
// متد موظفه هر دو پارامتر out رو مقداردهی کنه
firstName = fullName.Substring(0, i);
lastName = fullName.Substring(i + 1);
}

// --- نحوه استفاده ---
string fName, lName; // لازم نیست مقدار اولیه داشته باشن

Split("Stevie Ray Vaughan", out fName, out lName);

Console.WriteLine(fName); // خروجی: Stevie Ray
Console.WriteLine(lName); // خروجی: Vaughn


ترفندهای مدرن: out variables و Discards (_)


برای راحت‌تر شدن کار، #C دو تا قابلیت باحال برای out اضافه کرده:

1️⃣تعریف متغیر در لحظه (Out Variables):
لازم نیست متغیر رو از قبل تعریف کنید! می‌تونید همونجا موقع صدا زدن متد، تعریفش کنید:
Split("Stevie Ray Vaughan", out string firstName, out string lastName);
Console.WriteLine(lastName); // Vaughan


2️⃣نادیده گرفتن خروجی (Discards):
اگه به یکی از خروجی‌ها نیاز ندارید، می‌تونید با یه آندرلاین (_) اون رو نادیده بگیرید تا کدتون تمیزتر بشه:
// ما اینجا فقط به اسم کوچک نیاز داریم
Split("Stevie Ray Vaughan", out string fName, out _);
Console.WriteLine(fName); // Stevie Ray


🤔 حرف حساب و تجربه شما

این out یکی از پرکاربردترین کلمات کلیدی در کتابخانه‌های دات‌نته (مثلاً متد معروف int.TryParse). بلد بودنش خیلی به کارتون میاد.

شما بیشتر کجا از out استفاده کردید؟ آیا از قابلیت تعریف متغیر همزمان یا Discard خبر داشتید؟

نظراتتون رو کامنت کنید! 👇
[C# Geeks Hangout]

🔖 هشتگ‌ها:
#CSharp
#DotNet
#OutKeyword
🛡 ابزار حرفه‌ای #C :
بهینه‌سازی پرفورمنس با پارامتر in

فرض کنید یه struct خیلی بزرگ دارید (مثلاً با کلی فیلد). وقتی این struct رو به یه متد پاس میدید، #C یه کپی کامل ازش میسازه که می‌تونه روی پرفورمنس تأثیر منفی بذاره.

حالا اگه نخوایم این کپی‌کاری پرهزینه انجام بشه، ولی در عین حال مطمئن باشیم که متد، مقدار اصلی رو به هیچ وجه تغییر نمیده، چیکار کنیم؟
✨️اینجاست که کلمه کلیدی in وارد میدان میشه.


‌حالا in چیست؟ رفرنسِ فقط-خواندنی (Read-Only)
کلمه کلیدی in به کامپایلر میگه:

"این پارامتر رو بر اساس رفرنس بفرست تا از کپی کردنش جلوگیری بشه، ولی داخل متد، باهاش مثل یه مقدار فقط-خواندنی (Read-Only) رفتار کن و اجازه هیچ تغییری بهش نده."

🧨پس in دو تا کار خفن رو با هم انجام میده:
1️⃣افزایش پرفورمنس: از کپی شدن structهای بزرگ جلوگیری می‌کنه.


2️⃣تضمین ایمنی: به شما اطمینان میده که متد، داده‌ی اصلی شما رو دستکاری نمی‌کنه.


// فرض کنید این یک استراکت خیلی بزرگه
public readonly struct BigStruct
{
// ... کلی فیلد و پراپرتی
}

void ProcessData(in BigStruct data)
{
// این کد کامپایل نمیشه چون پارامتر 'data' فقط-خواندنی است
// data = new BigStruct(); // Compile-time error!

// ولی می‌تونیم ازش بخونیم و استفاده کنیم
Console.WriteLine("Processing data...");
}

// --- نحوه استفاده ---
var myBigData = new BigStruct();

// با 'in' به متد پاس میدیم تا از کپی شدن جلوگیری کنیم
ProcessData(in myBigData);

// اگه ابهامی در اورلود متد نباشه، بدون 'in' هم میشه صداش زد
ProcessData(myBigData);


🤔حرف حساب و تجربه شما

فهمیدیم in یکی از اون ابزارهای تخصصی‌تره که نشون میده شما به پرفورمنس و جزئیات اهمیت میدید. این کلمه کلیدی، قدرت ref (جلوگیری از کپی) و ایمنی pass-by-value (عدم تغییر مقدار اصلی) رو با هم ترکیب می‌کنه.

شما تا حالا از پارامتر in برای بهینه‌سازی کدهاتون استفاده کردید؟ یا اصلاً از وجودش خبر داشتید؟

خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.
[پاتوق گیک های #C]

🔖 هشتگ‌ها:
#CSharp
#Performance
#CodingTips
متدهای انعطاف‌پذیر در #C :
راهنمای کامل params و پارامترهای اختیاری

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

1️⃣params: پذیرش تعداد نامشخص آرگومان

کلمه کلیدی params به شما اجازه میده یه متد بنویسید که بتونه هر تعدادی آرگومان از یک نوع خاص رو به عنوان ورودی قبول کنه. این قابلیت برای متدهای کاربردی مثل توابع محاسباتی یا لاگرها فوق‌العاده‌ست.

جادوی پشت صحنه: کامپایلر #C به صورت خودکار، تمام آرگومان‌های ورودی شما رو که با کاما جدا شدن، میگیره و اون‌ها رو تبدیل به یه آرایه می‌کنه و به متد شما تحویل میده.

✨️قوانین کلیدی params:

قانون 1️⃣: params فقط و فقط می‌تونه برای آخرین پارامتر یک متد استفاده بشه.

قانون 2️⃣: نوع اون پارامتر باید یک آرایه یک‌بعدی باشه.

// با params، این متد هر تعداد int رو قبول می‌کنه
int Sum(params int[] numbers)
{
int total = 0;
// numbers در اینجا یک آرایه معمولی است
for (int i = 0; i < numbers.Length; i++)
{
total += numbers[i];
}
return total;
}

// --- نحوه استفاده ---
// شما می‌تونید هر تعداد آرگومان که خواستید، با کاما جدا کنید
int total1 = Sum(1, 2, 3, 4); // خروجی: 10

// یا حتی خودتون یه آرایه بهش پاس بدید
int[] myNumbers = { 10, 20, 30 };
int total2 = Sum(myNumbers); // خروجی: 60


2️⃣پارامترهای اختیاری: تعیین مقادیر پیش‌فرض

این قابلیت به شما اجازه میده برای پارامترهای متدتون، یک مقدار پیش‌فرض تعریف کنید. اگه کاربر موقع صدا زدن متد، مقداری برای اون پارامتر نفرسته، از همون مقدار پیش‌فرض استفاده میشه.

void RegisterUser(string username, string country = "Iran") 
{
Console.WriteLine($"User: {username}, Country: {country}");
}

// --- نحوه استفاده ---
RegisterUser("Ali", "Germany"); // User: Ali, Country: Germany
RegisterUser("Sara"); // User: Sara, Country: Iran


نکات فنی و قوانین مهم:

تله کامپایلر! مقدار پیش‌فرض در محل صدا زدن متد (calling side) قرار می‌گیره، نه در خود متد. یعنی RegisterUser("Sara") بعد از کامپایل، به RegisterUser("Sara", "Iran") تبدیل میشه.
نتیجه مهم:


●اگه شما یه کتابخونه بسازید و بعداً مقدار پیش‌فرض رو توش عوض کنید، پروژه‌هایی که از اون کتابخونه استفاده می‌کنن تا وقتی که دوباره کامپایل نشن، از همون مقدار پیش‌فرض قدیمی استفاده خواهند کرد!
●مقدار پیش‌فرض باید یک عبارت ثابت در زمان کامپایل باشه (مثل یک عدد، رشته، null یا default).

●پارامترهای اختیاری نمی‌تونن ref یا out باشن.

●در تعریف متد، پارامترهای اجباری باید قبل از پارامترهای اختیاری بیان.


🤔 حرف حساب و تجربه شما

این دو قابلیت، ابزارهای شما برای طراحی APIهای تمیز و انعطاف‌پذیر هستن.
از params وقتی استفاده کنید که تعداد ورودی‌ها نامشخصه.
از پارامترهای اختیاری وقتی استفاده کنید که یه پارامتر، یه مقدار پیش‌فرض رایج داره.

شما از کدوم یکی از این دو قابلیت بیشتر استفاده می‌کنید؟ آیا تا حالا به تله کامپایلری پارامترهای اختیاری برخورد کرده بودید؟

نظراتتون رو کامنت کنید! 👇
[C# Geeks Hangout]

🔖 هشتگ‌ها:
#Parameters
#OptionalParameters
#Params
🏷 خداحافظی با اشتباهات ترتیب پارامترها:
قدرت Named Arguments در #C

تا حالا شده یه متد با چند تا ورودی از یک نوع (مثلاً چند تا int یا bool) داشته باشید و موقع صدا زدنش، جای دو تا آرگومان رو با هم اشتباه بگیرید؟ یا ندونید هر مقدار مال کدوم پارامتره؟

😎سی‌شارپ با قابلیت آرگومان‌های نام‌دار (Named Arguments) این مشکل رو برای همیشه حل کرده و خوانایی کد شما رو به شدت بالا می‌بره.

1️⃣آرگومان نام‌دار چیست؟

خیلی ساده‌ست! به جای اینکه به ترتیب، فقط مقدارها رو به متد پاس بدید، می‌تونید اسم پارامتر رو بنویسید، بعد دو نقطه (:) و بعد مقدارش رو.
void Foo(int x, int y) 
{
Console.WriteLine($"x: {x}, y: {y}");
}

// صدا زدن متد با آرگومان‌های نام‌دار
Foo(x: 1, y: 2); // خروجی: x: 1, y: 2


2️⃣قدرت اصلی: بی‌نیازی از ترتیب!

زیبایی این قابلیت اینه که وقتی از اسم پارامترها استفاده می‌کنید، دیگه ترتیب مهم نیست! می‌تونید اون‌ها رو به هر ترتیبی که دوست دارید به متد پاس بدید. این کار، کد رو خیلی خواناتر می‌کنه.
// این دو خط کد دقیقاً یک کار یکسان رو انجام میدن
Foo(x: 1, y: 2);
Foo(y: 2, x: 1);


3️⃣ترکیب با آرگومان‌های معمولی(Positional) ⚠️

شما می‌تونید آرگومان‌های معمولی (بدون نام) و نام‌دار رو با هم ترکیب کنید، اما یه قانون مهم داره: آرگومان‌های معمولی باید همیشه قبل از آرگومان‌های نام‌دار بیان.
//  درسته: اول معمولی، بعد نام‌دار
Foo(1, y: 2);

// خطای کامپایل: نمی‌تونی بعد از نام‌دار، معمولی بیاری
// Foo(x: 1, 2); // این کار معمولاً توصیه نمیشه، هرچند اگه آرگومان در جایگاه درستش باشه، کامپایلر قبول می‌کنه



4️⃣بهترین کاربرد: پارامترهای اختیاری

قدرت واقعی آرگومان‌های نام‌دار، وقتی مشخص میشه که با پارامترهای اختیاری ترکیب بشن.

فرض کنید متدی با چندین پارامتر اختیاری دارید و فقط می‌خواید مقدار آخری رو تغییر بدید. بدون آرگومان نام‌دار، باید برای تمام پارامترهای قبلی هم مقدار پیش‌فرضشون رو دوباره بنویسید! اما با این قابلیت، کار خیلی ساده میشه:
void Bar(int a = 0, int b = 0, int c = 0, int d = 0) 
{
Console.WriteLine($"a:{a}, b:{b}, c:{c}, d:{d}");
}

// فقط پارامتر d رو مقداردهی می‌کنیم و بقیه پیش‌فرض باقی می‌مونن
Bar(d: 3); // خروجی: a:0, b:0, c:0, d:3


🤔 حرف حساب و تجربه شما

آرگومان‌های نام‌دار ابزار فوق‌العاده‌ای برای افزایش خوانایی و کاهش باگ‌های ناشی از ترتیب اشتباه پارامترها هستن، به خصوص در متدهایی با تعداد ورودی زیاد.

شما بیشتر کجا از Named Arguments استفاده می‌کنید؟ آیا این قابلیت به تمیزتر شدن کدهاتون کمک کرده؟

خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.

[پاتوق گیک های #C]

🔖 هشتگ‌ها:
#CSharp
#DotNet
#CleanCode
🔬 تکنیک‌های پیشرفته #C :
شیرجه عمیق در ref locals و ref returns

آماده‌اید که به بخش‌های عمیق و کمتر دیده‌شده #C سفر کنیم؟ امروز می‌خوایم در مورد دو تا قابلیت قدرتمند ولی خاص صحبت کنیم که برای بهینه‌سازی‌های سطح پایین و کارهای حرفه‌ای استفاده میشن: ref locals و ref returns.

اینها ابزارهای روزمره شما نیستن، ولی شناختنشون شما رو به درک عمیق‌تری از قدرت و انعطاف #C می‌رسونه.

1️⃣این ref local چیست؟ یک نام مستعار برای حافظه
یه ref local، یه متغیر محلیه که یک کپی از مقدار نیست، بلکه یک ارجاع یا نام مستعار مستقیم به حافظه‌ی یک متغیر دیگه‌ست (مثل یک عنصر آرایه یا یک فیلد).

این یعنی هر تغییری روی این متغیر، مستقیماً روی مقدار اصلی اعمال میشه!
int[] numbers = { 0, 1, 2, 3, 4 };

// numRef حالا یک نام دیگر برای numbers[2] است
ref int numRef = ref numbers[2];

// هر تغییری روی numRef، مستقیماً روی عنصر آرایه اعمال میشه
numRef *= 10;

Console.WriteLine(numRef); // خروجی: 20
Console.WriteLine(numbers[2]); // خروجی: 20 (عنصر اصلی هم تغییر کرد!)

2️⃣حالا ref return چیست؟ برگرداندن آدرس به جای مقدار 💥
یه متد می‌تونه به جای برگردوندن مقدار یک متغیر، رفرنس یا آدرس حافظه‌ی اون رو برگردونه. این کار به کدی که متد رو صدا زده، اجازه دسترسی مستقیم و تغییر مقدار اصلی رو میده.
class Program
{
static string x = "Old Value";

// این متد، رفرنس به فیلد x رو برمی‌گردونه
static ref string GetX() => ref x;

static void Main()
{
// xRef یک رفرنس مستقیم به x میشه
ref string xRef = ref GetX();

// تغییر xRef، خودِ متغیر استاتیک x رو تغییر میده
xRef = "New Value";

Console.WriteLine(x); // خروجی: New Value
}
}


3️⃣نوبت ref readonly: ترکیب پرفورمنس و ایمنی 🛡
گاهی وقتا شما می‌خواید از مزیت پرفورمنس برگردوندن رفرنس (جلوگیری از کپی شدن داده‌های بزرگ) استفاده کنید، ولی نمی‌خواید کدی که اون رو دریافت کرده، بتونه مقدار اصلی رو تغییر بده.

اینجاست که ref readonly وارد میشه. با این قابلیت، شما رفرنس رو برمی‌گردونید، ولی اون رفرنس فقط-خواندنی خواهد بود.

4️⃣هشدار و کاربرد اصلی ⚠️
این قابلیت‌ها ابزارهای روزمره شما نیستن. اون‌ها برای micro optimization های خاص طراحی شدن، به خصوص در سناریوهای پرفورمنس بالا مثل کار با <Span<T یا در بازی‌سازی که هر نانوثانیه مهمه.

در ۹۹٪ مواقع، شما به این‌ها نیاز ندارید و کد ساده‌تر، همیشه بهتره.

🤔 حرف حساب و تجربه شما

آشنایی با این مفاهیم، حتی اگه ازشون استفاده نکنید، دید شما رو نسبت به قابلیت‌های سطح پایین و قدرت #C عمیق‌تر می‌کنه.

آیا تا حالا از ref locals یا ref returns تو پروژه‌ای استفاده کردید؟ یا اصلاً از وجودشون خبر داشتید؟

خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.

[C# Geeks Hangout]

🔖 هشتگ‌ها:
#Ref
#CSharp
#AdvancedCSharp
🔬 کالبدشکافی var در #C :
ابزار قدرتمند یا کدنویسی شلخته؟

کلمه کلیدی var یکی از مدرن‌ترین و در عین حال بحث‌برانگیزترین قابلیت‌های #C هست. بعضی‌ها عاشقشن و بعضی‌ها ازش فراری‌ان.

اما var دقیقاً چیه؟ آیا #C رو مثل جاوااسکریپت، داینامیک می‌کنه؟ بیاید یک بار برای همیشه، این ابزار قدرتمند رو کالبدشکافی کنیم.

1️⃣حالا var چیست؟ استنتاج نوع در زمان کامپایل 🤖

این var یه کلمه کلیدی برای راحتی کاره. وقتی از var استفاده می‌کنید، به کامپایلر میگید:

"من نوع این متغیر محلی رو نمی‌نویسم. خودت از روی عبارتی که دارم بهش اختصاص میدم، نوعش رو استنتاج (Infer) کن."
// کامپایلر می‌فهمه که x از نوع string هست
var x = "hello";

// کامپایلر می‌فهمه که y از نوع StringBuilder هست
var y = new System.Text.StringBuilder();

// کامپایلر می‌فهمه که z از نوع float هست
var z = (float)Math.PI;


این کدها دقیقاً معادل این هستن که شما خودتون نوع رو به صورت صریح بنویسید.

2️⃣مهم‌ترین نکته: var داینامیک نیست! (Statically Typed) 🛡

این بزرگترین تصور اشتباه در مورد var هست. استفاده از var به هیچ وجه #C رو به یه زبان داینامیک تبدیل نمی‌کنه.

نوع متغیری که با var تعریف میشه، در زمان کامپایل مشخص و قفل میشه و دیگه هرگز قابل تغییر نیست. var فقط برای خلاصه‌نویسیه.
// اینجا کامپایلر نوع x رو int تشخیص میده و این نوع برای همیشه ثابت می‌مونه
var x = 5;

// خطای زمان کامپایل!
// شما نمی‌تونید یه رشته رو تو یه متغیر از نوع int بریزید.
x = "hello";


3️⃣تله خوانایی: کی نباید از var استفاده کنیم؟ 🧐

با اینکه var کد رو کوتاه‌تر می‌کنه، گاهی وقتا می‌تونه خوانایی کد رو کم کنه. قانون کلی اینه: اگه با یه نگاه به سمت راست مساوی، نتونستید نوع متغیر رو به راحتی تشخیص بدید، بهتره از var استفاده نکنید.
// اینجا x از چه نوعیه؟ int? long?
// برای فهمیدنش باید بریم و متد Next رو چک کنیم.
// این کد خوانایی خوبی نداره.
var x = new Random().Next();

// نوشتن صریح، اینجا خیلی بهتر و خواناتره:
int x = new Random().Next();


🤔 حرف حساب و استایل شما

کلمه کلیدی var یه ابزار عالی برای خلاصه‌نویسی و تمیزتر کردن کده، به شرطی که هوشمندانه ازش استفاده بشه و خوانایی رو فدای کوتاهی نکنیم.

نکته: سناریوهایی هم وجود داره (مثل کار با Anonymous Types) که استفاده از var در اون‌ها اجباریه و بعداً بهشون می‌رسیم.

شما از طرفدارای var هستید یا مخالفش؟ به نظرتون کجاها استفاده از var کد رو بهتر می‌کنه و کجاها بدتر؟

خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.

[پاتوق گیک های #C]

🔖 هشتگ‌ها:
#CSharp
#CodingTips #CleanCode #Var
یک ترفند مدرن برای خداحافظی با تکرار: Target-Typed new

از نوشتن اسم‌های طولانی مثل StringBuilder دو بار تو یه خط خسته شدی؟
StringBuilder sb = new System.Text.StringBuilder();

این تکرار، کد رو شلوغ و ناخوانا می‌کنه. #C از نسخه ۹ به بعد، یه راه حل خیلی شیک برای این مشکل داره:
Target-Typed new Expressions.


معرفی ()Target-Typed new 🎯
قانونش ساده‌ست: اگه کامپایلر بتونه از روی "هدف" (Target) - یعنی متغیری که داری بهش مقدار میدی یا پارامتر متدی که داری بهش پاس میدی - نوع رو تشخیص بده، شما دیگه لازم نیست اسم نوع رو بعد از new تکرار کنی!
// روش قدیمی و تکراری
System.Text.StringBuilder sb1 = new System.Text.StringBuilder("Old way");

// روش مدرن و تمیز با Target-Typed new
System.Text.StringBuilder sb2 = new("New way"); // کامپایلر خودش می‌فهمه!


✨️این قابلیت دو جا قدرت اصلیش رو نشون میده:
1️⃣مقداردهی فیلدها در سازنده (Constructor):

وقتی یه فیلد رو تو کلاس تعریف می‌کنی و می‌خوای تو سازنده مقداردهی کنی:
class Foo
{
private System.Text.StringBuilder _sb;

public Foo(string initialValue)
{
// نیازی به تکرار اسم طولانی StringBuilder نیست
_sb = new(initialValue);
}
}


2️⃣پاس دادن آبجکت جدید به عنوان آرگومان متد:

// کد خیلی کوتاه و خوانا میشه
MyMethod(new("test"));

void MyMethod(System.Text.StringBuilder sb) { /* ... */ }


🤔 حرف حساب و تجربه شما

این یه قابلیت کوچیک ولی خیلی کاربردیه که به مرور، کد شما رو تمیزتر و مدرن‌تر می‌کنه و از تکرارهای بی‌مورد جلوگیری می‌کنه.

شما از این سینتکس جدید ()new استفاده می‌کنید؟ به نظرتون خوانایی کد رو بهتر می‌کنه یا ترجیح میدید همیشه نوع رو کامل بنویسید؟

خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.
[پاتوق گیک های #C]

🔖 هشتگ‌ها:
#CSharp #DotNet #ModernCSharp #CleanCode #CodingTips
⚙️ الفبای منطق در #C :
عبارت‌ها (Expressions) و عملگرها (Operators)

تا حالا به این فکر کردید که ساده‌ترین کدهایی که می‌نویسید، مثل 12 * 30 یا x + 1، پشت صحنه چطور تفسیر میشن؟ درک این موضوع، الفبای منطق کدنویسیه و به شما دید عمیق‌تری نسبت به ساختار کد میده.

بیاید با دو تا از بنیادی‌ترین مفاهیم آشنا بشیم: عبارت‌ها و عملگرها.

1️⃣عبارت (Expression) چیست؟

خیلی ساده‌ست: هر چیزی در کد که در نهایت یک مقدار (Value) تولید می‌کنه، یک عبارت نامیده میشه.

ساده‌ترین عبارت‌ها، ثابت‌ها (Constants) و متغیرها (Variables) هستن:

عبارت‌ها می‌تونن با هم ترکیب بشن و عبارت‌های پیچیده‌تری بسازن. در واقع، ورودی‌های یک عملگر، خودشون می‌تونن عبارت باشن:
// اینجا (12 * 30) خودش یک عبارته که به عنوان ورودی به عملگر + داده شده
1 + (12 * 30)


2️⃣عملگر (Operator) چیست؟

عملگرها، ابزارهایی هستن که یک یا چند "عملوند" (Operand) (که همون عبارت‌ها هستن) رو به عنوان ورودی می‌گیرن و یک مقدار جدید رو به عنوان خروجی تولید می‌کنن.

عملگرها در #C بر اساس تعداد عملوندهاشون به سه دسته تقسیم میشن:

●یکانی (Unary): روی یک عملوند کار می‌کنه (مثل x++ یا -x).

●دوگانی (Binary): روی دو عملوند کار می‌کنه (مثل x + y). این‌ها همیشه وسط دو عملوند میان (بهش میگن Infix notation).

●سه‌گانی (Ternary): تنها عملگری که روی سه عملوند کار می‌کنه (q ? a : b).

🤔 حرف حساب و دیدگاه شما

درک این مفاهیم پایه، به شما کمک می‌کنه که منطق کد رو مثل یک معمار ببینید که با آجرها (عبارت‌ها) و ملات (عملگرها)، یه ساختمون کامل می‌سازه.

شما هم کد رو اینجوری به اجزای سازنده‌ش تقسیم می‌کنید؟ آیا دونستن این مفاهیم پایه، به درک بهتر شما از کدهای پیچیده کمک کرده؟

خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.
[پاتوق گیک های #C]

🔖 هشتگ‌ها:
#DotNet #CodingTips #SoftwareEngineering
🧱 مفاهیم بنیادی #C :
عبارت‌های اولیه و عبارت‌های پوچ (Void)

تا حالا به یه خط کد مثل Math.Log(1) نگاه کردید و فکر کنید اجزای سازنده‌ش در سطح زبان چین؟ #C مفاهیم پایه‌ای داره که دونستنشون، دید ما رو به ساختار کد عمیق‌تر می‌کنه.

امروز با دو تا از این مفاهیم بنیادی آشنا میشیم.

1️⃣عبارت‌های اولیه (Primary Expressions)

این‌ها پایه‌ای‌ترین و ذاتی‌ترین عبارت‌ها در زبان هستن که از عملگرهای اصلی مثل . (دسترسی به عضو) و () (فراخوانی متد) تشکیل میشن. در واقع، آجرهای اصلی سازنده منطق کد شما هستن.
// این یک عبارت است که خود از دو عبارت اولیه تشکیل شده:

// ۱. عبارت اول (Math.Log):
// یک 'member lookup' که متد Log رو در کلاس Math پیدا می‌کنه.

// ۲. عبارت دوم ((1)):
// یک 'method call' که متد پیدا شده رو با ورودی 1 صدا می‌زنه.

Math.Log(1);


2️⃣عبارت‌های پوچ (Void Expressions)

یه عبارت پوچ، عبارتیه که هیچ مقداری برنمی‌گردونه. بهترین مثالش، صدا زدن یه متد با نوع خروجی void هست.

چون این عبارت‌ها هیچ مقداری ندارن، شما نمی‌تونید ازشون به عنوان ورودی (عملوند) برای عملگرهای دیگه استفاده کنید.
// این خط کد خطای زمان کامپایل میده.
// چرا؟ چون Console.WriteLine(1) یک عبارت پوچه و مقداری نداره
// که بشه اون رو با عدد 1 جمع کرد!
int result = 1 + Console.WriteLine(1); // Compile-time error!


🤔 حرف حساب

دونستن این دو مفهوم تئوری، بهتون کمک می‌کنه که دلیل بعضی از خطاهای زمان کامپایل رو بهتر درک کنید و با دید عمیق‌تری کد بخونید.

آیا تا حالا به این فکر کرده بودید که چرا نمی‌تونید خروجی Console.WriteLine رو توی یه متغیر بریزید؟ حالا دلیلش رو می‌دونید!

نظراتتون رو کامنت کنید! 👇
[@CSharpGeeksChat]

🔖 هشتگ‌ها:
#Programming #Fundamentals #DotNet #Compiler #Expressions
👑 قوانین نانوشته #C :
اولویت و ترتیب اجرای عملگرها

وقتی عبارتی مثل 1 + 2 * 3 رو می‌نویسید، #C از کجا می‌دونه که اول باید ضرب رو انجام بده؟ یا چرا 8 / 4 / 2 میشه 1 و نه 4؟

جواب تو دو تا قانون کلیدیه که امروز یاد می‌گیریم:
●اولویت (Precedence)
●ترتیب اجرا (Associativity).

1️⃣عبارت‌های انتساب (=) و ترفندهاش ✍️

اول از همه، بدونید که خودِ انتساب (=) در #C یک "عبارت" هست و مقدار داره! مقدارش هم همون چیزیه که بهش اختصاص داده شده. این ویژگی به ما اجازه میده کدهای جالبی بنویسیم:

زنجیره‌ای کردن انتساب: برای مقداردهی اولیه چند متغیر:
int a, b, c;
a = b = c = 0; // هر سه متغیر برابر با صفر میشن

عملگرهای ترکیبی: این‌ها میانبرهای syntactic برای ترکیب انتساب با یه عملگر دیگه‌ان و کد رو تمیزتر می‌کنن:
int x = 5;
x *= 2; // معادل: x = x * 2; حالا x برابر 10 است


2️⃣اولویت عملگرها (Precedence): چه کسی رئیس است؟

مثل ریاضی مدرسه، بعضی عملگرها در #C "زورشان" بیشتره. کامپایلر همیشه اول سراغ عملگرهای با اولویت بالاتر میره.

اولویت * و / از + و - بیشتره.

به همین دلیله که عبارت زیر، اینجوری محاسبه میشه:
// کامپایلر این رو به صورت 1 + (2 * 3) می‌بینه
int result = 1 + 2 * 3; // خروجی: 7


3️⃣ترتیب اجرا (Associativity): چپ به راست یا راست به چپ؟
حالا اگه اولویت‌ها یکی بود چی؟ اینجا "ترتیب اجرا" وارد میشه.

چپ-به-راست (Left-associative):
بیشتر عملگرهای دوتایی در #C چپ-به-راست هستن. یعنی محاسبه از چپ شروع میشه.
// کامپایلر این رو به صورت (8 / 4) / 2 می‌بینه
int result = 8 / 4 / 2; // خروجی: 1

راست-به-چپ (Right-associative):
اما عملگرهای انتساب (=)، شرطی سه‌تایی (?:) و null-coalescing (??) استثنا هستن و از راست به چپ ارزیابی میشن.
این ویژگی به ما اجازه میده که انتساب زنجیره‌ای داشته باشیم:
int x, y;
// کامپایلر این رو به صورت (x = (y = 3)) می‌بینه
// اول 3 در y ریخته میشه، و بعد حاصل اون عبارت (که 3 هست) در x ریخته میشه.
x = y = 3;


🤔 حرف حساب و تجربه شما

تسلط بر این قوانین، شما رو از خیلی از باگ‌های محاسباتی نجات میده و بهتون کمک می‌کنه کد بقیه رو سریع‌تر بخونید.

آیا تا حالا باگی داشتید که به خاطر رعایت نکردن اولویت عملگرها به وجود اومده باشه؟ یا از قابلیت زنجیره‌ای کردن انتساب (a=b=c) استفاده می‌کنید؟

خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.

[C# Geeks Hangout]

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #CodingTips #Fundamentals #Operators
🛡 نجات از NullReferenceException: جادوی اپراتورهای مدرن #C 🪄

تو پست‌های قبلی در مورد null و خطای معروفش 😭 حرف زدیم. حالا وقتشه با سه تا از قوی‌ترین اسلحه‌های #C ⚔️ برای مقابله با این خطا و نوشتن کدهای امن‌تر و خواناتر آشنا بشیم: ?.، ?? و ??=.

این سه اپراتور، جعبه ابزار مدرن شما برای نوشتن کدهای ضد-null هستن.

1️⃣ اپراتور Null-Conditional (?.): امن‌ترین راه دسترسی

این اپراتور که بهش "الویس" هم میگن، مثل یه نگهبان شخصیه 🕵️‍♂️. قبل از اینکه به یه عضو یا متد دسترسی پیدا کنه، چک می‌کنه: "صاحابخونه هست؟ 🤔".

اگه آبجکت null نبود ، کارشو انجام میده.

اگه آبجکت null بود ، بدون هیچ سر و صدایی 🤫 کل عبارت رو متوقف می‌کنه و null برمی‌گردونه.
StringBuilder sb = null;

// به جای اینکه خطا بده، s برابر با null میشه
string s = sb?.ToString();

// این قابلیت زنجیره‌ای هم هست!
// چون sb نال هست، اصلاً به ToUpper() نمیرسه و خطا نمیده
string upper = sb?.ToString().ToUpper();

تله مهم 🪤: خروجی این عبارت میتونه null باشه، پس باید اون رو در نوعی بریزید که null رو قبول می‌کنه (مثلاً int خالی نمی‌تونه، ولی int? می‌تونه).

2️⃣ اپراتور Null-Coalescing (??): تعیین مقدار پیش‌فرض

این اپراتور، زوج عالی برای ?. هست. منطقش اینه:

"اگه چیزی که سمت چپم هست، null نبود، همونو بده. اگه null بود، این مقدار پیش‌فرض رو بده ."

این دوتا با هم یه ترکیب طلایی 🏆 می‌سازن:
StringBuilder sb = null;

// اگه sb نال نبود، ToString() رو برگردون
// اگه نال بود، رشته "Default Value" رو برگردون
string s = sb?.ToString() ?? "Default Value";

Console.WriteLine(s); // خروجی: Default Value


3️⃣ اپراتور Null-Coalescing Assignment (??=)

مقداردهی هوشمند این اپراتور که از 8 #C اضافه شده، یه میانبر خیلی تمیزه. منطقش اینه:

"فقط و فقط اگه متغیر سمت چپم null هست، این مقدار جدید رو بهش اختصاص بده ✍️."
myVariable ??= someDefaultValue;

دقیقاً معادل این کد طولانی‌تره:
if (myVariable == null)
{
myVariable = someDefaultValue;
}


🤔 حرف حساب و تجربه شما

این سه اپراتور، جعبه ابزار مدرن شما برای نوشتن کدهای #C تمیز، کوتاه و مقاوم در برابر خطای null هستن.

شما از کدوم یکی از این اپراتورها بیشتر استفاده می‌کنید؟ آیا ترکیب ?. و ?? جزو ترفندهای روزمره شما هست؟


خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.
[پاتوق گیک های #C]

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #NullHandling #CodingTips #BestPractices
⚖️ قوانین محلی در #C :
همه چیز درباره متغیرها، Scope و const

هر متدی در #C از یه سری دستور (Statement) تشکیل شده. اما این دستورها، به خصوص وقتی متغیر جدیدی تعریف می‌کنیم، قوانین خاصی دارن.

امروز می‌خوایم با قوانین متغیرهای محلی (Local Variables) و محدوده دیدشون یا همون Scope آشنا بشیم.

1️⃣ دستورهای تعریف (Declaration Statements)

این دستورها یه متغیر جدید به برنامه معرفی می‌کنن. می‌تونید همزمان با تعریف، مقداردهی هم بکنید.

💯ترفند جالب: تعریف چند متغیر از یک نوع در یک خط:
bool rich = true, famous = false;
int x = 1, y = 2, z = 3;


کلمه کلیدی const:
اگه مقداری دارید که هرگز نباید تغییر کنه، اون رو با const (ثابت) تعریف کنید. constها باید حتماً موقع تعریف، مقداردهی بشن و بعد از اون غیرقابل تغییرن.
const double Pi = 3.14159;
// Pi = 3.15; // خطای زمان کامپایل!


2️⃣ محدوده دید یا Scope

🚫قانون براکت‌ها {} :
در #C، هر بلوک کدی که داخل آکولاد {} قرار می‌گیره، یه "محله" یا Scope جدید می‌سازه.

قانون اصلی Scope: متغیرهایی که تو این محله تعریف میشن، فقط همینجا "زندگی" می‌کنن و بیرون از این بلوک، دیگه شناخته شده نیستن. همچنین شما نمی‌تونید تو یه محله، دو تا متغیر با اسم یکسان تعریف کنید.
void SomeMethod()
{
int x = 10; // x در کل متد SomeMethod قابل دسترسه

{ // شروع یک اسکوپ داخلی جدید
int y = 20; // y فقط داخل این براکت‌ها وجود داره
// int x = 5; // خطا: x قبلاً در این محدوده (اسکوپ بالاتر) تعریف شده
Console.WriteLine(x); // درسته، چون x از بیرون دیده میشه
}

// Console.WriteLine(y); // خطا: y اینجا دیگه وجود نداره و از بین رفته
}


3️⃣ نکته عجیب و مهم #C:گستردگی Scope

یه نکته عجیب در #C اینه که محدوده دید یه متغیر، کل بلوک کدش هست، حتی خط‌های قبل از تعریفش!

برای همین اگه یه متغیر رو پایین یه بلاک تعریف کنید، نمی‌تونید بالاترش تو همون بلاک، یکی دیگه به همون اسم تعریف کنید.
void AnotherMethod()
{
int i = 5;
if (i == 5)
{
// با اینکه i اینجا تعریف شده، اسکوپش کل بلاک if هست
// برای همین خط پایین خطا میده
// int i = 10; // خطا: i قبلاً در این اسکوپ تعریف شده

int j = 20;
}
// Console.WriteLine(j); // خطا: j فقط داخل if زنده بود
}


🤔 حرف حساب و تجربه شما

درک درست Scope، کلید اصلی نوشتن کدهای تمیز و بدون خطای کامپایل هست.

شما تا حالا به خاطر این قوانین Scope به خطای "a variable with this name is already defined" برخورد کردید؟ یا نکته‌ی گستردگی Scope در #C براتون جدید بود؟

خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.
[پاتوق گیک های #C]

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #Scope #Variables #Fundamentals
🧠 مغز تصمیم‌گیری در #C: راهنمay کامل دستور if-else


چطور به برنامه‌مون یاد بدیم که فکر کنه، شرایط رو بسنجه و تصمیم بگیره؟ ابزار اصلی و روزمره ما برای این کار، دستور قدرتمند و حیاتی if هست. بیاید با تمام جزئیاتش آشنا بشیم.

1️⃣ دستور if: اگر این شرط درست بود...
ساده‌ترین حالت. یه شرط (که باید حاصلش true یا false باشه) رو داخل پرانتز بررسی می‌کنه. اگه شرط true بود، بلوک کد داخلش اجرا میشه. اگه false بود، کلاً ازش رد میشه.
if (5 < 2 * 3) // شرط 5 < 6 درست است (true)
{
Console.WriteLine("شرط درست بود و این پیام چاپ شد.");
}


2️⃣ دستور else: در غیر این صورت...
else همیشه به یه if وصله و میگه: "اگه شرط if بالایی false بود، به جای اون، این بلوک کد رو اجرا کن."
if (2 + 2 == 5) // شرط غلط است (false)
{
// این بخش اجرا نمیشه
Console.WriteLine("Does not compute");
}
else
{
// چون شرط بالا غلط بود، این بخش اجرا میشه
Console.WriteLine("شرط غلط بود و این پیام چاپ شد.");
}


3️⃣ زنجیره‌ای کردن شرط‌ها با else if
اگه چند تا شرط مختلف رو می‌خوای پشت سر هم چک کنی، از else if استفاده می‌کنی. #C شرط‌ها رو به ترتیب چک می‌کنه و به محض اینکه به اولین شرط true برسه، بلوک مربوط به اون رو اجرا می‌کنه و از کل ساختار if-else خارج میشه.
int score = 85;
char grade;

if (score >= 90)
{
grade = 'A';
}
else if (score >= 80)
{
// چون 85 >= 80 درست است، این بلوک اجرا میشه و تمام!
// دیگه شرط‌های بعدی چک نمیشن.
grade = 'B';
}
else if (score >= 70)
{
grade = 'C';
}
else
{
grade = 'F';
}

Console.WriteLine($"Your grade is: {grade}"); // خروجی: Your grade is: B


🤔 حرف حساب و تجربه شما

این if-else ستون فقرات منطق در اکثر برنامه‌هاست و تسلط بر اون برای نوشتن هر کدی ضروریه.

شما بیشتر برای چه سناریوهایی از if-else if-else های تودرتو استفاده می‌کنید؟ آیا جایگزین بهتری مثل switch (که بعداً بهش می‌رسیم) رو ترجیح میدید؟

خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامه‌ی بحث، سوالات، غر زدن‌ها و گپ و گفت‌های خودمونی، فقط تو گروه.
[پاتوق گیک های #C]

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #ControlFlow #IfElse #CodingTips
Forwarded from thisisnabi.dev [Farsi]
یه بعضی موقع ها اینقدر برنامه نویسی رو دوست دارم که توی ۴۸ ساعت، ۴۲ ساعت کد می نویسم.
بعضی موقع ها هم اینقدر حال به هم زن میشه که می خوام برم پیک موتوری کار کنم ول کنم همه چی رو :/