C# Geeks (.NET) – Telegram
⚙️ الفبای منطق در #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]
یه بعضی موقع ها اینقدر برنامه نویسی رو دوست دارم که توی ۴۸ ساعت، ۴۲ ساعت کد می نویسم.
بعضی موقع ها هم اینقدر حال به هم زن میشه که می خوام برم پیک موتوری کار کنم ول کنم همه چی رو :/
💡 10 فرمان برای معماری تمیز در ASP.NET Core

کد تمیز مساوی است با یک سیستم مقیاس‌پذیر. این قوانین معماری رو دنبال کنید تا پروژه‌تون قابل نگهداری (maintainable) و توسعه‌دهنده‌پسند (developer-friendly) باقی بمونه.

1️⃣ از تزریق وابستگی (DI) همه‌جا استفاده کنید - هرگز سرویس‌هاتون رو با new نسازید.

2️⃣ کنترلرهاتون رو لاغر نگه دارید، منطق اصلی رو به لایه سرویس منتقل کنید.

3️⃣ مسئولیت‌ها رو با استفاده از اینترفیس‌ها و اصول SOLID جدا کنید.

4️⃣ برای جداسازی منطق خواندن/نوشتن، از الگوی CQRS استفاده کنید.

5️⃣ هرگز از داخل کنترلر مستقیماً به دیتابیس دسترسی پیدا نکنید - همیشه از طریق یک Repository یا سرویس این کار رو انجام بدید.

6️⃣ برای شکل‌دهی به داده‌ها بین لایه‌ها، از DTO ها استفاده کنید - از ارسال مستقیم Entityهای دیتابیس به بیرون خودداری کنید.

7️⃣ اعتبارسنجی (Validation) رو با کتابخانه‌هایی مثل FluentValidation یا DataAnnotations اضافه کنید - هرگز کورکورانه به داده‌های ورودی اعتماد نکنید.

8️⃣ برای دغدغه‌های مشترک (cross-cutting concerns) مثل لاگینگ، مدیریت خطا و CORS، از Middleware ها استفاده کنید.

9️⃣ پروژه‌تون رو به لایه‌ها ساختاربندی کنید: API، Application، Domain، Infrastructure.

🔟 برای سرویس‌هاتون Unit Test بنویسید - اگه تست کردن یه تیکه کد سخت باشه، اون کد یه بوی بدی میده (code smell)!

این قوانین رو دنبال کنید و اپلیکیشن‌های .NET Core شما بعداً ازتون تشکر خواهند کرد. 😉
🤔 تله‌ی else سرگردان در #C:
چرا براکت {} بهترین دوست شماست؟

به این قطعه کد نگاه کنید. به نظرتون else برای کدوم if اجرا میشه؟ اولی یا دومی؟
if (true)
if (false)
Console.WriteLine("Line 1");
else
Console.WriteLine("Line 2"); // این خط اجرا میشه! اما چرا؟


جواب این سوال می‌تونه باعث باگ‌های خیلی بدی تو برنامه‌تون بشه. بیاید این تله کلاسیک رو بررسی کنیم.

1️⃣ قانون else سرگردان (The Dangling Else Rule)

قانون #C (و خیلی از زبان‌های دیگه) اینه: یک else همیشه به نزدیک‌ترین if قبلی در همان بلوک کد که هنوز else نداره، متصل میشه.

پس کامپایلر، کد بالا رو در واقع اینجوری می‌بینه و تفسیر می‌کنه:
if (true)
{
// else به این if متصل شده
if (false)
Console.WriteLine("Line 1");
else
Console.WriteLine("Line 2");
}


چون شرط if اول true هست، وارد بلوک داخلی میشیم. چون شرط if دوم false هست، else مربوط به همون if دوم اجرا میشه.

2️⃣ راه حل: قدرت براکت‌ها {} 🛡

بهترین راه برای جلوگیری از این ابهام و نوشتن کد خوانا و بدون باگ، اینه که همیشه از براکت {} برای بدنه‌ی if و else استفاده کنید، حتی اگه فقط یک خط کد دارید!

با براکت، شما صراحتاً و بدون هیچ ابهامی به کامپایلر (و بقیه توسعه‌دهنده‌ها) میگید که منظورتون چیه.

حالا ببینید با جابجا کردن براکت، چطور منطق کد کاملاً عوض میشه:
if (true)
{
if (false)
Console.WriteLine("Line 1");
}
else // حالا این else مال if اولی است!
{
Console.WriteLine("Line 2"); // و دیگر اجرا نمی‌شود.
}


3️⃣ تنها استثنای زیبا: الگوی else if

تنها جایی که ننوشتن براکت‌های اضافی کاملاً رایج و خواناست، الگوی معروف else if هست. با اینکه از نظر فنی این هم یه if تودرتوئه، ولی #C و IDEها این الگو رو به خوبی می‌شناسن و فرمت می‌کنن.
void TellMeWhatICanDo(int age)
{
if (age >= 35)
Console.WriteLine("You can be president!");
else if (age >= 21)
Console.WriteLine("You can drink!");
else if (age >= 18)
Console.WriteLine("You can vote!");
else
Console.WriteLine("You can wait!");
}


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

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

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

[C# Geeks Hangout]

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #CleanCode #IfElse #BestPractices
🔀 دستور switch:
جایگزین تمیز برای if-elseهای تودرتو

از نوشتن if-else if-elseهای طولانی و تودرتو خسته شدید؟ برای وقت‌هایی که می‌خواید یه متغیر رو با چندین مقدار ثابت مقایسه کنید، #C یه راه حل خیلی تمیزتر و خواناتر داره: دستور switch.

1️⃣ ساختار اصلی switch

ساختارش ساده‌ست: شما یه متغیر رو به switch میدید و بعد با استفاده از case، حالت‌های مختلفی که اون متغیر می‌تونه داشته باشه رو بررسی می‌کنید.

ساختار case: مقدار ثابتی که می‌خوای بررسی کنی.

ساختار break: مهم‌ترین بخش! بعد از اینکه کد یه case اجرا شد، break باعث میشه که از کل بلوک switch خارج بشیم. اگه break رو نذارید، کدتون خطا میده!
ساختار default: اگه هیچکدوم از caseها با مقدار متغیر نخوندن، این بلوک اجرا میشه. مثل else نهایی عمل می‌کنه.

void ShowCard(int cardNumber)
{
switch (cardNumber)
{
case 13:
Console.WriteLine("King");
break;
case 12:
Console.WriteLine("Queen");
break;
case 11:
Console.WriteLine("Jack");
break;
default: // برای بقیه اعداد
Console.WriteLine(cardNumber);
break;
}
}

2️⃣ تکنیک‌های پیشرفته‌تر switch کلاسیک

این switch کلاسیک دو تا ترفند جالب دیگه هم داره:

🧱 روی هم چیدن caseها:

اگه می‌خواید برای چند تا case مختلف، یه کد یکسان اجرا بشه، می‌تونید اون‌ها رو پشت سر هم و بدون break بنویسید:

switch (cardNumber)
{
case 13:
case 12:
case 11:
Console.WriteLine("Face card");
break;
default:
Console.WriteLine("Plain card");
break;
}


⬆️پرش با goto case:

یه قابلیت کمتر شناخته شده، goto case هست که به شما اجازه میده از یک case به یه case دیگه بپرید:
switch (cardNumber)
{
case 12:
Console.WriteLine("Queen");
break;
case -1: // جوکر
goto case 12; // جوکر مثل بی‌بی حساب میشه!
// ... بقیه case ها
}

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

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

شما بیشتر از switch استفاده می‌کنید یا if-else if؟ جایی بوده که switch واقعاً کدتون رو تمیزتر کرده باشه؟

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #ControlFlow #SwitchCase #CleanCode
🚀 انقلاب switch در #C مدرن: Pattern Matching

تو پست قبلی، با switch کلاسیک آشنا شدیم. اما داستان اینجا تموم نمیشه! از #C 7 به بعد، switch یه تحول بزرگ داشته و به یه ابزار فوق‌العاده قدرتمند به اسم Pattern Matching مجهز شده.

بیاید ببینیم این قابلیت‌های جدید چی هستن و چطور switch رو از یه ابزار ساده، به یه غول تبدیل کردن.

1️⃣ سوییچ روی نوع (Switching on Type)
دیگه محدود به مقادیر ثابت نیستید! حالا می‌تونید یه متغیر از نوع object رو به switch بدید و بر اساس نوع واقعی اون در زمان اجرا، تصمیم‌گیری کنید و حتی همون لحظه اون رو تو یه متغیر جدید بریزید.
void TellMeTheType(object x)
{
switch (x)
{
// اگه x از نوع int بود، اون رو در متغیر i بریز و این بلوک رو اجرا کن
case int i:
Console.WriteLine($"It's an int! Square is {i * i}");
break;
// اگه از نوع string بود...
case string s:
Console.WriteLine($"It's a string! Length is {s.Length}");
break;
case null:
Console.WriteLine("It's null");
break;
default:
Console.WriteLine("I don't know what it is");
break;
}
}


2️⃣ اضافه کردن شرط با when

گاهی اوقات، فقط چک کردن نوع کافی نیست و می‌خواید یه شرط اضافه هم داشته باشید. کلمه کلیدی when به شما اجازه میده دقیقاً همین کار رو بکنید.
void ProcessShape(object shape)
{
switch (shape)
{
// این case فقط برای دایره‌هایی اجرا میشه که شعاعشون بزرگتر از 10 هست
case Circle c when c.Radius > 10:
Console.WriteLine("Big circle");
break;

case Circle c:
Console.WriteLine("Small or medium circle");
break;

case bool b when b == true: // فقط وقتی که بولین، true باشه
Console.WriteLine("It's true!");
break;
}
}


3️⃣ نکات تکمیلی و مهم

اهمیت ترتیب: برخلاف switch کلاسیک، در Pattern Matching ترتیب caseها مهمه! #C اون‌ها رو از بالا به پایین چک می‌کنه و به محض رسیدن به اولین گزینه‌ی منطبق، کار تموم میشه.

روی هم چیدن caseها: می‌تونید چند case مختلف رو برای اجرای یک کد مشترک، روی هم بچینید:
switch (x)
{
case float f when f > 1000:
case double d when d > 1000:
case decimal m when m > 1000:
Console.WriteLine("It's a large number!");
break;
}


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

این Pattern Matching، دستور switch رو از یه ابزار ساده به یه غول قدرتمند برای کار با داده‌ها و انواع مختلف تبدیل کرده.

شما از این قابلیت‌های مدرن switch تو کدهاتون استفاده می‌کنید؟ کدوم ویژگیش (سوییچ روی نوع، when، ...) براتون کاربردی‌تر بوده؟

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #PatternMatching #SwitchCase #ModernCSharp
از دستور به عبارت: تکامل switch در #C مدرن (Switch Expressions)

تو پست‌های قبلی با switch کلاسیک و switch با Pattern Matching آشنا شدیم. اما انقلاب switch اینجا تموم نمیشه! از C# 8 به بعد، switch می‌تونه به عنوان یک عبارت (Expression) هم استفاده بشه.

یعنی چی؟ یعنی می‌تونه یه مقدار رو برگردونه! این قابلیت، کدهای شرطی رو به شدت کوتاه‌تر و خواناتر می‌کنه.

1️⃣ معرفی switch expression: خداحافظی با case و break

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

متغیر قبل از switch میاد.

به جای case x: و break;، از x => result, استفاده می‌کنیم.

برای حالت default، از _ (discard pattern) استفاده می‌کنیم.
string cardName = cardNumber switch
{
13 => "King",
12 => "Queen",
11 => "Jack",
_ => "Pip card" // معادل default
};


نکته مهم ⚠️: برخلاف switch statement، اگه تو یه switch expression حالت پیش‌فرض (_) رو نذارید و هیچکدوم از حالت‌ها هم با مقدار ورودی نخونه، برنامه‌تون با یه Exception کرش می‌کنه!
2️⃣ قدرت اصلی: سوییچ روی چند مقدار با Tuple Pattern

قدرت واقعی switch expression وقتی مشخص میشه که می‌فهمید می‌تونید روی چند تا مقدار همزمان سوییچ کنید! این کار با استفاده از Tuples انجام میشه.
string cardName = (cardNumber, suite) switch
{
(13, "spades") => "King of spades",
(13, "clubs") => "King of clubs",
(12, "spades") => "Queen of spades",
// ...
_ => "Some other card"
};


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

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

این switch expression یکی از بهترین قابلیت‌های مدرن #C برای نوشتن کدهای تابعی (Functional)، خوانا و خلاصه‌ست و در LINQ هم بسیار پرکاربرده.

شما از switch expression تو کدهاتون استفاده می‌کنید؟ به نظرتون این سینتکس از switch statement قدیمی بهتره؟

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #ModernCSharp #SwitchExpression #CleanCode
کدام کلمه کلیدی در #C برای جلوگیری از تغییر مقدار یک متغیر بعد از تعریف اولیه استفاده می‌شود؟
Anonymous Quiz
6%
static
13%
readonly
75%
const
6%
fixed
🔄 تکرار کد بدون تکرار! راهنمای کامل حلقه‌ها (Loops) در #C

چطور می‌تونیم یه کار رو صد بار انجام بدیم، بدون اینکه صد خط کد بنویسیم؟ با استفاده از حلقه‌ها (Loops)! حلقه‌ها ستون فقرات هر الگوریتم پیچیده‌ای هستن و به ما اجازه میدن یک بلوک کد رو بارها و بارها تکرار کنیم.

امروز با ۴ نوع اصلی حلقه در #C آشنا میشیم.

1️⃣ حلقه while: تا وقتی که...
این ساده‌ترین نوع حلقه‌ست. یه شرط bool رو بررسی می‌کنه و تا وقتی اون شرط true باشه، بلوک کد رو تکرار می‌کنه.

نکته کلیدی: شرط قبل از هر بار اجرای بدنه حلقه چک میشه. پس اگه شرط از اول false باشه، بدنه حلقه هیچوقت اجرا نمیشه.
int i = 0;
while (i < 3)
{
Console.Write(i); // 012
i++;
}


2️⃣ حلقه do-while: حداقل یک بار اجرا کن!
این حلقه خیلی شبیه while هست، با این تفاوت مهم که شرط رو بعد از اجرای بلوک کد چک می‌کنه.

نتیجه مهم: این یعنی تضمین میشه که بدنه حلقه حداقل یک بار اجرا بشه، حتی اگه شرط از اول false باشه.
int i = 0;
do
{
Console.Write(i); // 012
i++;
}
while (i < 3);


3️⃣ حلقه for: حلقه همه‌کاره و قدرتمند 🔢
این حلقه برای تکرارهایی که تعدادشون مشخصه، عالیه. سه بخش اصلی و قدرتمند داره:
for (بخش مقداردهی اولیه; بخش شرط; بخش گام تکرار)

مقداردهی اولیه: فقط یک بار، قبل از شروع حلقه اجرا میشه (معمولاً برای تعریف شمارنده).

شرط: قبل از هر بار تکرار، این شرط bool چک میشه.

گام تکرار: بعد از هر بار اجرای بدنه حلقه، این بخش اجرا میشه (معمولاً برای افزایش شمارنده).
for (int i = 0; i < 3; i++)
{
Console.Write(i); // 012
}


مثال پیشرفته (دنباله فیبوناچی):
// محاسبه ۱۰ عدد اول دنباله فیبوناچی
for (int i = 0, prevFib = 1, curFib = 1; i < 10; i++)
{
Console.WriteLine(prevFib);
int newFib = prevFib + curFib;
prevFib = curFib;
curFib = newFib;
}


نکته حرفه‌ای: شما می‌تونید هر کدوم از سه بخش for رو خالی بذارید. مثلاً for (;;) یه حلقه بی‌نهایته!

4️⃣ حلقه foreach: پیمایش کلکسیون‌ها به سبک مدرن
این مدرن‌ترین، خواناترین و امن‌ترین راه برای حرکت روی تمام اعضای یک مجموعه قابل پیمایش (مثل آرایه یا string) هست. دیگه نگران ایندکس و خطای IndexOutOfRangeException نیستید!
// پیمایش روی تمام کاراکترهای رشته "beer"
foreach (char c in "beer")
{
Console.WriteLine(c);
}
// خروجی:
// b
// e
// e
// r


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

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

شما تو کدهاتون بیشتر از کدوم نوع حلقه استفاده می‌کنید؟ for یا foreach؟ سناریوی جالبی دارید که توش do-while بهترین انتخاب بوده باشه؟

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #ControlFlow #Loops #ForEach #ForLoop
🚀 پرش‌های حرفه‌ای در #C: راهنمای کامل break, continue, return, throw و goto

برنامه همیشه خط به خط اجرا نمیشه. گاهی وقتا لازمه از یه حلقه بپریم بیرون، یه تکرار رو رد کنیم، یا کل متد رو متوقف کنیم. #C برای این "پرش"ها، چند تا دستور کلیدی داره که بهشون میگیم Jump Statements.
بیاید با این ابزارهای قدرتمند برای کنترل جریان اجرا آشنا بشیم.

💡نکته مهم: تمام این دستورات پرش، از قوانین بلوک try...finally پیروی می‌کنن. یعنی اگه از داخل یه try به بیرون بپرید، بلوک finally همیشه قبل از پرش اجرا میشه.

1️⃣ break: فرار از حلقه!

دستور break مثل یه درِ خروج اضطراری برای حلقه‌ها (for, while, ...) و switch عمل می‌کنه. به محض اجرا، حلقه یا switch رو فوراً متوقف می‌کنه و اجرا به اولین خط بعد از اون منتقل میشه.
int i = 0;
while (true) // حلقه بی‌نهایت
{
if (i > 5)
break; // از حلقه فرار کن!

Console.Write(i + " ");
i++;
}
// خروجی: 0 1 2 3 4 5
// اجرا از اینجا ادامه پیدا می‌کنه


2️⃣ continue: این یکی رو بی‌خیال شو!

continue مثل دکمه "اسکیپ" برای تکرار فعلی حلقه‌ست. بقیه کدهای داخل حلقه رو برای این تکرار نادیده می‌گیره و مستقیم میره سراغ شرط و گام تکرار بعدی.
for (int i = 0; i < 10; i++)
{
if ((i % 2) == 0) // اگه عدد زوجه
continue; // این تکرار رو بی‌خیال شو و برو سراغ i بعدی

Console.Write(i + " ");
}
// خروجی: 1 3 5 7 9


3️⃣ return: ماموریت انجام شد!

return به متد میگه "کار من اینجا تموم شد!" و اجرا رو به جایی که متد صدا زده شده بود، برمی‌گردونه. اگه متد خروجی داشته باشه (non-void)، return باید اون مقدار رو هم با خودش برگردونه.
decimal AsPercentage(decimal d)
{
decimal p = d * 100m;
return p; // با مقدار p به بیرون از متد برگرد
}


4️⃣ throw: اعلام وضعیت قرمز!

این throw برای پرتاب کردن یه Exception و اعلام وضعیت خطاست. وقتی یه throw اجرا میشه، اجرای عادی متوقف میشه و #C دنبال یه بلوک catch برای مدیریت اون خطا می‌گرده (که بعداً مفصل بهش می‌رسیم).
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException("Name cannot be null or empty!");
}


5️⃣ goto: شمشیر دولبه (و خطرناک!)

goto قدیمی‌ترین و قدرتمندترین دستور پرشه، ولی استفاده ازش در ۹۹٪ مواقع توصیه نمیشه چون می‌تونه کد رو به "کد اسپاگتی" تبدیل کنه که دنبال کردنش خیلی سخته. با این حال، دونستنش برای شناخت کامل زبان خوبه. goto اجرا رو به یک لیبل (label) منتقل می‌کنه.
int i = 1;
startLoop: // این یک لیبل است
if (i <= 5)
{
Console.Write(i + " ");
i++;
goto startLoop; // به لیبل startLoop بپر
}
// خروجی: 1 2 3 4 5


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

تسلط بر این دستورات پرش، به شما کنترل کاملی روی جریان اجرای برنامه‌تون میده.

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

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #ControlFlow #BestPractices #Exception
خروجی کد زیر چیست؟
int x = 5;
Console.WriteLine(++x);
Anonymous Quiz
45%
5
50%
6
5%
Compile Time Erorr
0%
4
📂 نظم و ترتیب در #C: همه چیز درباره namespace (از روش کلاسیک تا 10 #C)

وقتی پروژه‌هاتون بزرگ میشه و تعداد کلاس‌ها زیاد میشه، چطور ازش یه آش شله‌قلمکار نسازیم؟ ابزار اصلی #C برای سازماندهی و جلوگیری از تداخل اسمی، namespace هست.

این namespace مثل یه سیستم پوشه‌بندیه (folders) برای کدهاتون. شما می‌تونید کلاس‌های مرتبط رو تو یه namespace بذارید تا هم پیداکردنشون راحت‌تر باشه و هم اگه دو تا کلاس با اسم یکسان تو دو تا پوشه مختلف داشتید، با هم قاطی نشن.

1️⃣ روش کلاسیک تعریف namespace

در روش سنتی، شما یک بلوک namespace تعریف می‌کنید و کلاس‌هاتون رو داخلش قرار میدید. برای ایجاد ساختار تودرتو، می‌تونید از نقطه استفاده کنید.
// روش تودرتو با استفاده از نقطه (روش پیشنهادی)
namespace MyProject.Services.Authentication
{
class AuthService { }
class TokenService { }
}

// این کد معادل کد بالاست ولی باعث تو رفتگی (indentation) بیشتر میشه
namespace MyProject
{
namespace Services
{
namespace Authentication
{
class AuthService { }
class TokenService { }
}
}
}


برای استفاده از یک کلاس، باید اسم کاملش رو به همراه namespace وارد کنید، مگر اینکه اون namespace رو بالای فایل using کرده باشید.

2️⃣ روش مدرن (از 10 #C): File-Scoped Namespaces

تیم #C دید که معمولاً تمام کلاس‌های یه فایل، تو یه namespace مشترک هستن. پس از 10 #C به بعد، یه راه خیلی تمیزتر معرفی کردن که کل فایل رو داخل یه namespace قرار میده و از یه لایه تو رفتگی اضافی جلوگیری می‌کنه.

قبل از 10 #C:
namespace MyNamespace
{
class Class1
{
// Code...
}

class Class2
{
// Code...
}
}

از 10 #C به بعد:
namespace MyNamespace; // این برای کل فایل اعمال میشه و تمام!

class Class1
{
// Code...
}

class Class2
{
// Code...
}


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

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

استفاده درست از namespaceها، اولین قدم برای نوشتن یه پروژه بزرگه که قابل نگهداری باشه.

شما تو پروژه‌هاتون چقدر روی ساختار namespaceها وقت میذارید؟ از قابلیت جدید File-Scoped Namespaces استفاده می‌کنید؟

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #CleanCode #BestPractices #Namespace
🏛 اصول SOLID: پنج ستون اصلی برای ساخت نرم‌افزار حرفه‌ای

تا حالا شده به کدی برگردید که چند ماه پیش نوشتید و دیگه هیچی ازش نفهمید؟ یا بخواید یه تغییر کوچیک بدید و ببینید کل برنامه به هم ریخت؟

💡این مشکلات یه راه حل معروف دارن: اصول SOLID.

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

حالا SOLID مخفف چیست؟ 🤔
هر حرف در SOLID، نماینده یک اصله:

1️⃣ S - Single Responsibility Principle (اصل تک مسئولیتی):
یک کلاس باید فقط و فقط یک دلیل برای تغییر داشته باشه.
2️⃣ O - Open/Closed Principle (اصل باز/بسته):
کد شما باید برای "توسعه" باز، ولی برای "تغییر" بسته باشه.
3️⃣ L - Liskov Substitution Principle (اصل جایگزینی لیسکوف):
باید بتونید یک نمونه از کلاس فرزند رو به جای کلاس پدر استفاده کنید، بدون اینکه برنامه به مشکل بخوره.
4️⃣ I - Interface Segregation Principle (اصل تفکیک اینترفیس‌ها):
کلاس‌ها نباید مجبور بشن اینترفیس‌هایی رو پیاده‌سازی کنن که بهشون نیازی ندارن.
5️⃣ D - Dependency Inversion Principle (اصل وارونگی وابستگی):
ماژول‌های سطح بالا نباید به ماژول‌های سطح پایین وابسته باشن؛ هر دو باید به "انتزاع" (Abstraction) وابسته باشن.
🚀 شروع مینی-سریال جدید!
امروز، قراره یه مینی-سریال داشته باشیم و هر کدوم از این ۵ اصل رو به صورت جداگانه، با زبون ساده و مثال‌های عملی در #C کالبدشکافی کنیم.

این سری، سطح شما رو از "کدنویس" به "معمار نرم‌افزار" نزدیک‌تر می‌کنه.

با ما همراه باشید!
💬 بحث و گفتگوی بیشتر در گروه کامیونیتی:
[C# Geeks Community]

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #SOLID #SoftwareArchitecture #CleanCode #BestPractices