🏷 خداحافظی با اشتباهات ترتیب پارامترها:
تا حالا شده یه متد با چند تا ورودی از یک نوع (مثلاً چند تا int یا bool) داشته باشید و موقع صدا زدنش، جای دو تا آرگومان رو با هم اشتباه بگیرید؟ یا ندونید هر مقدار مال کدوم پارامتره؟
😎سیشارپ با قابلیت آرگومانهای نامدار (Named Arguments) این مشکل رو برای همیشه حل کرده و خوانایی کد شما رو به شدت بالا میبره.
خیلی سادهست! به جای اینکه به ترتیب، فقط مقدارها رو به متد پاس بدید، میتونید اسم پارامتر رو بنویسید، بعد دو نقطه (:) و بعد مقدارش رو.
زیبایی این قابلیت اینه که وقتی از اسم پارامترها استفاده میکنید، دیگه ترتیب مهم نیست! میتونید اونها رو به هر ترتیبی که دوست دارید به متد پاس بدید. این کار، کد رو خیلی خواناتر میکنه.
شما میتونید آرگومانهای معمولی (بدون نام) و نامدار رو با هم ترکیب کنید، اما یه قانون مهم داره: آرگومانهای معمولی باید همیشه قبل از آرگومانهای نامدار بیان.
قدرت واقعی آرگومانهای نامدار، وقتی مشخص میشه که با پارامترهای اختیاری ترکیب بشن.
فرض کنید متدی با چندین پارامتر اختیاری دارید و فقط میخواید مقدار آخری رو تغییر بدید. بدون آرگومان نامدار، باید برای تمام پارامترهای قبلی هم مقدار پیشفرضشون رو دوباره بنویسید! اما با این قابلیت، کار خیلی ساده میشه:
آرگومانهای نامدار ابزار فوقالعادهای برای افزایش خوانایی و کاهش باگهای ناشی از ترتیب اشتباه پارامترها هستن، به خصوص در متدهایی با تعداد ورودی زیاد.
شما بیشتر کجا از Named Arguments استفاده میکنید؟ آیا این قابلیت به تمیزتر شدن کدهاتون کمک کرده؟
خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامهی بحث، سوالات، غر زدنها و گپ و گفتهای خودمونی، فقط تو گروه.
[پاتوق گیک های #C]
قدرت 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 :
آمادهاید که به بخشهای عمیق و کمتر دیدهشده #C سفر کنیم؟ امروز میخوایم در مورد دو تا قابلیت قدرتمند ولی خاص صحبت کنیم که برای بهینهسازیهای سطح پایین و کارهای حرفهای استفاده میشن: ref locals و ref returns.
اینها ابزارهای روزمره شما نیستن، ولی شناختنشون شما رو به درک عمیقتری از قدرت و انعطاف #C میرسونه.
1️⃣این ref local چیست؟ یک نام مستعار برای حافظه
یه ref local، یه متغیر محلیه که یک کپی از مقدار نیست، بلکه یک ارجاع یا نام مستعار مستقیم به حافظهی یک متغیر دیگهست (مثل یک عنصر آرایه یا یک فیلد).
این یعنی هر تغییری روی این متغیر، مستقیماً روی مقدار اصلی اعمال میشه!
2️⃣حالا ref return چیست؟ برگرداندن آدرس به جای مقدار 💥
یه متد میتونه به جای برگردوندن مقدار یک متغیر، رفرنس یا آدرس حافظهی اون رو برگردونه. این کار به کدی که متد رو صدا زده، اجازه دسترسی مستقیم و تغییر مقدار اصلی رو میده.
3️⃣نوبت ref readonly: ترکیب پرفورمنس و ایمنی 🛡
گاهی وقتا شما میخواید از مزیت پرفورمنس برگردوندن رفرنس (جلوگیری از کپی شدن دادههای بزرگ) استفاده کنید، ولی نمیخواید کدی که اون رو دریافت کرده، بتونه مقدار اصلی رو تغییر بده.
اینجاست که ref readonly وارد میشه. با این قابلیت، شما رفرنس رو برمیگردونید، ولی اون رفرنس فقط-خواندنی خواهد بود.
4️⃣هشدار و کاربرد اصلی ⚠️
این قابلیتها ابزارهای روزمره شما نیستن. اونها برای micro optimization های خاص طراحی شدن، به خصوص در سناریوهای پرفورمنس بالا مثل کار با <Span<T یا در بازیسازی که هر نانوثانیه مهمه.
در ۹۹٪ مواقع، شما به اینها نیاز ندارید و کد سادهتر، همیشه بهتره.
آشنایی با این مفاهیم، حتی اگه ازشون استفاده نکنید، دید شما رو نسبت به قابلیتهای سطح پایین و قدرت #C عمیقتر میکنه.
آیا تا حالا از ref locals یا ref returns تو پروژهای استفاده کردید؟ یا اصلاً از وجودشون خبر داشتید؟
خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامهی بحث، سوالات، غر زدنها و گپ و گفتهای خودمونی، فقط تو گروه.
[C# Geeks Hangout]
شیرجه عمیق در 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 رو مثل جاوااسکریپت، داینامیک میکنه؟ بیاید یک بار برای همیشه، این ابزار قدرتمند رو کالبدشکافی کنیم.
این var یه کلمه کلیدی برای راحتی کاره. وقتی از var استفاده میکنید، به کامپایلر میگید:
"من نوع این متغیر محلی رو نمینویسم. خودت از روی عبارتی که دارم بهش اختصاص میدم، نوعش رو استنتاج (Infer) کن."
این کدها دقیقاً معادل این هستن که شما خودتون نوع رو به صورت صریح بنویسید.
این بزرگترین تصور اشتباه در مورد var هست. استفاده از var به هیچ وجه #C رو به یه زبان داینامیک تبدیل نمیکنه.
نوع متغیری که با var تعریف میشه، در زمان کامپایل مشخص و قفل میشه و دیگه هرگز قابل تغییر نیست. var فقط برای خلاصهنویسیه.
با اینکه var کد رو کوتاهتر میکنه، گاهی وقتا میتونه خوانایی کد رو کم کنه. قانون کلی اینه: اگه با یه نگاه به سمت راست مساوی، نتونستید نوع متغیر رو به راحتی تشخیص بدید، بهتره از var استفاده نکنید.
کلمه کلیدی var یه ابزار عالی برای خلاصهنویسی و تمیزتر کردن کده، به شرطی که هوشمندانه ازش استفاده بشه و خوانایی رو فدای کوتاهی نکنیم.
شما از طرفدارای var هستید یا مخالفش؟ به نظرتون کجاها استفاده از 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 :
تا حالا به این فکر کردید که سادهترین کدهایی که مینویسید، مثل 12 * 30 یا x + 1، پشت صحنه چطور تفسیر میشن؟ درک این موضوع، الفبای منطق کدنویسیه و به شما دید عمیقتری نسبت به ساختار کد میده.
بیاید با دو تا از بنیادیترین مفاهیم آشنا بشیم: عبارتها و عملگرها.
خیلی سادهست: هر چیزی در کد که در نهایت یک مقدار (Value) تولید میکنه، یک عبارت نامیده میشه.
سادهترین عبارتها، ثابتها (Constants) و متغیرها (Variables) هستن:
عبارتها میتونن با هم ترکیب بشن و عبارتهای پیچیدهتری بسازن. در واقع، ورودیهای یک عملگر، خودشون میتونن عبارت باشن:
عملگرها، ابزارهایی هستن که یک یا چند "عملوند" (Operand) (که همون عبارتها هستن) رو به عنوان ورودی میگیرن و یک مقدار جدید رو به عنوان خروجی تولید میکنن.
عملگرها در #C بر اساس تعداد عملوندهاشون به سه دسته تقسیم میشن:
●یکانی (Unary): روی یک عملوند کار میکنه (مثل x++ یا -x).
●دوگانی (Binary): روی دو عملوند کار میکنه (مثل x + y). اینها همیشه وسط دو عملوند میان (بهش میگن Infix notation).
●سهگانی (Ternary): تنها عملگری که روی سه عملوند کار میکنه (q ? a : b).
درک این مفاهیم پایه، به شما کمک میکنه که منطق کد رو مثل یک معمار ببینید که با آجرها (عبارتها) و ملات (عملگرها)، یه ساختمون کامل میسازه.
شما هم کد رو اینجوری به اجزای سازندهش تقسیم میکنید؟ آیا دونستن این مفاهیم پایه، به درک بهتر شما از کدهای پیچیده کمک کرده؟
خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامهی بحث، سوالات، غر زدنها و گپ و گفتهای خودمونی، فقط تو گروه.
[پاتوق گیک های #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 :
تا حالا به یه خط کد مثل Math.Log(1) نگاه کردید و فکر کنید اجزای سازندهش در سطح زبان چین؟ #C مفاهیم پایهای داره که دونستنشون، دید ما رو به ساختار کد عمیقتر میکنه.
امروز با دو تا از این مفاهیم بنیادی آشنا میشیم.
اینها پایهایترین و ذاتیترین عبارتها در زبان هستن که از عملگرهای اصلی مثل . (دسترسی به عضو) و () (فراخوانی متد) تشکیل میشن. در واقع، آجرهای اصلی سازنده منطق کد شما هستن.
یه عبارت پوچ، عبارتیه که هیچ مقداری برنمیگردونه. بهترین مثالش، صدا زدن یه متد با نوع خروجی void هست.
چون این عبارتها هیچ مقداری ندارن، شما نمیتونید ازشون به عنوان ورودی (عملوند) برای عملگرهای دیگه استفاده کنید.
دونستن این دو مفهوم تئوری، بهتون کمک میکنه که دلیل بعضی از خطاهای زمان کامپایل رو بهتر درک کنید و با دید عمیقتری کد بخونید.
آیا تا حالا به این فکر کرده بودید که چرا نمیتونید خروجی Console.WriteLine رو توی یه متغیر بریزید؟ حالا دلیلش رو میدونید!
نظراتتون رو کامنت کنید! 👇
[@CSharpGeeksChat]
عبارتهای اولیه و عبارتهای پوچ (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).
اول از همه، بدونید که خودِ انتساب (=) در #C یک "عبارت" هست و مقدار داره! مقدارش هم همون چیزیه که بهش اختصاص داده شده. این ویژگی به ما اجازه میده کدهای جالبی بنویسیم:
زنجیرهای کردن انتساب: برای مقداردهی اولیه چند متغیر:
عملگرهای ترکیبی: اینها میانبرهای syntactic برای ترکیب انتساب با یه عملگر دیگهان و کد رو تمیزتر میکنن:
مثل ریاضی مدرسه، بعضی عملگرها در #C "زورشان" بیشتره. کامپایلر همیشه اول سراغ عملگرهای با اولویت بالاتر میره.
اولویت * و / از + و - بیشتره.
به همین دلیله که عبارت زیر، اینجوری محاسبه میشه:
3️⃣ترتیب اجرا (Associativity): چپ به راست یا راست به چپ؟
حالا اگه اولویتها یکی بود چی؟ اینجا "ترتیب اجرا" وارد میشه.
چپ-به-راست (Left-associative):
بیشتر عملگرهای دوتایی در #C چپ-به-راست هستن. یعنی محاسبه از چپ شروع میشه.
راست-به-چپ (Right-associative):
اما عملگرهای انتساب (=)، شرطی سهتایی (?:) و null-coalescing (??) استثنا هستن و از راست به چپ ارزیابی میشن.
این ویژگی به ما اجازه میده که انتساب زنجیرهای داشته باشیم:
تسلط بر این قوانین، شما رو از خیلی از باگهای محاسباتی نجات میده و بهتون کمک میکنه کد بقیه رو سریعتر بخونید.
آیا تا حالا باگی داشتید که به خاطر رعایت نکردن اولویت عملگرها به وجود اومده باشه؟ یا از قابلیت زنجیرهای کردن انتساب (a=b=c) استفاده میکنید؟
خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامهی بحث، سوالات، غر زدنها و گپ و گفتهای خودمونی، فقط تو گروه.
[C# Geeks Hangout]
اولویت و ترتیب اجرای عملگرها
وقتی عبارتی مثل 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 :
هر متدی در #C از یه سری دستور (Statement) تشکیل شده. اما این دستورها، به خصوص وقتی متغیر جدیدی تعریف میکنیم، قوانین خاصی دارن.
امروز میخوایم با قوانین متغیرهای محلی (Local Variables) و محدوده دیدشون یا همون Scope آشنا بشیم.
این دستورها یه متغیر جدید به برنامه معرفی میکنن. میتونید همزمان با تعریف، مقداردهی هم بکنید.
💯ترفند جالب: تعریف چند متغیر از یک نوع در یک خط:
کلمه کلیدی const:
اگه مقداری دارید که هرگز نباید تغییر کنه، اون رو با const (ثابت) تعریف کنید. constها باید حتماً موقع تعریف، مقداردهی بشن و بعد از اون غیرقابل تغییرن.
🚫قانون براکتها {} :
در #C، هر بلوک کدی که داخل آکولاد {} قرار میگیره، یه "محله" یا Scope جدید میسازه.
قانون اصلی Scope: متغیرهایی که تو این محله تعریف میشن، فقط همینجا "زندگی" میکنن و بیرون از این بلوک، دیگه شناخته شده نیستن. همچنین شما نمیتونید تو یه محله، دو تا متغیر با اسم یکسان تعریف کنید.
یه نکته عجیب در #C اینه که محدوده دید یه متغیر، کل بلوک کدش هست، حتی خطهای قبل از تعریفش!
برای همین اگه یه متغیر رو پایین یه بلاک تعریف کنید، نمیتونید بالاترش تو همون بلاک، یکی دیگه به همون اسم تعریف کنید.
درک درست Scope، کلید اصلی نوشتن کدهای تمیز و بدون خطای کامپایل هست.
شما تا حالا به خاطر این قوانین Scope به خطای "a variable with this name is already defined" برخورد کردید؟ یا نکتهی گستردگی Scope در #C براتون جدید بود؟
خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامهی بحث، سوالات، غر زدنها و گپ و گفتهای خودمونی، فقط تو گروه.
[پاتوق گیک های #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 اجرا میشه؟ اولی یا دومی؟
جواب این سوال میتونه باعث باگهای خیلی بدی تو برنامهتون بشه. بیاید این تله کلاسیک رو بررسی کنیم.
قانون #C (و خیلی از زبانهای دیگه) اینه: یک else همیشه به نزدیکترین if قبلی در همان بلوک کد که هنوز else نداره، متصل میشه.
پس کامپایلر، کد بالا رو در واقع اینجوری میبینه و تفسیر میکنه:
چون شرط if اول true هست، وارد بلوک داخلی میشیم. چون شرط if دوم false هست، else مربوط به همون if دوم اجرا میشه.
بهترین راه برای جلوگیری از این ابهام و نوشتن کد خوانا و بدون باگ، اینه که همیشه از براکت {} برای بدنهی if و else استفاده کنید، حتی اگه فقط یک خط کد دارید!
با براکت، شما صراحتاً و بدون هیچ ابهامی به کامپایلر (و بقیه توسعهدهندهها) میگید که منظورتون چیه.
حالا ببینید با جابجا کردن براکت، چطور منطق کد کاملاً عوض میشه:
تنها جایی که ننوشتن براکتهای اضافی کاملاً رایج و خواناست، الگوی معروف else if هست. با اینکه از نظر فنی این هم یه if تودرتوئه، ولی #C و IDEها این الگو رو به خوبی میشناسن و فرمت میکنن.
نوشتن براکتهای اضافی یه عادت سادهست که شما رو از ساعتها دیباگ کردن در آینده نجات میده.
شما جزو کدوم دستهاید؟ اونایی که همیشه از براکت استفاده میکنن یا اونایی که برای کدهای تکخطی حذفش میکنن؟ آیا تا حالا به خاطر همین موضوع به باگ خوردید؟
خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامهی بحث، سوالات، غر زدنها و گپ و گفتهای خودمونی، فقط تو گروه.
[C# Geeks Hangout]
چرا براکت {} بهترین دوست شماست؟
به این قطعه کد نگاه کنید. به نظرتون 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های طولانی و تودرتو خسته شدید؟ برای وقتهایی که میخواید یه متغیر رو با چندین مقدار ثابت مقایسه کنید، #C یه راه حل خیلی تمیزتر و خواناتر داره: دستور switch.
ساختارش سادهست: شما یه متغیر رو به switch میدید و بعد با استفاده از case، حالتهای مختلفی که اون متغیر میتونه داشته باشه رو بررسی میکنید.
این switch کلاسیک دو تا ترفند جالب دیگه هم داره:
اگه میخواید برای چند تا case مختلف، یه کد یکسان اجرا بشه، میتونید اونها رو پشت سر هم و بدون break بنویسید:
یه قابلیت کمتر شناخته شده، goto case هست که به شما اجازه میده از یک case به یه case دیگه بپرید:
با اینکه switch در نسخههای جدید #C خیلی قدرتمندتر شده (که تو پست بعدی بهش میپردازیم)، همین نسخه کلاسیکش هم ابزار فوقالعادهای برای تمیزتر کردن منطقهای شرطی شماست.
شما بیشتر از switch استفاده میکنید یا if-else if؟ جایی بوده که switch واقعاً کدتون رو تمیزتر کرده باشه؟
خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامهی بحث، سوالات، غر زدنها و گپ و گفتهای خودمونی، فقط تو گروه.
[پاتوق گیک های #C]
جایگزین تمیز برای 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