C# Geeks (.NET)
334 subscribers
128 photos
1 video
98 links
Download Telegram
5️⃣ اصل پنجم SOLID: وارونگی وابستگی (Dependency Inversion Principle)

تا حالا شده یه کلاس بنویسید که داخلش یه کلاس دیگه رو با new می‌سازید و بعداً برای تغییر اون کلاس داخلی، مجبور میشید کلاس اصلی رو هم دستکاری کنید؟ این یعنی کدهای شما به هم سفت و سخت (Tightly Coupled) وصل شدن.

اصل وارونگی وابستگی (DIP) برای حل همین مشکل و ایجاد کدهای انعطاف‌پذیر طراحی شده.

این اصل چی میگه؟ 🎯
این اصل دو بخش مهم داره:
ماژول‌های سطح بالا نباید به ماژول‌های سطح پایین وابسته باشند. هر دو باید به انتزاع (Abstraction) وابسته باشند.

انتزاع‌ها نباید به جزئیات وابسته باشند. این جزئیات هستن که باید به انتزاع‌ها وابسته باشند.
به زبان ساده: کلاس‌های اصلی و سطح بالای شما (مثلاً بیزنس لاجیک) نباید به جزئیات پیاده‌سازی (مثلاً نحوه کار با دیتابیس یا ارسال ایمیل) وابسته باشن. در عوض، هر دو باید به یک قرارداد مشترک (Interface) وابسته باشن.

مثال عملی: سیستم اطلاع‌رسانی
فرض کنید یه سیستمی برای اطلاع‌رسانی به کاربر داریم.

مثال بد (نقض اصل وارونگی وابستگی):
اینجا کلاس سطح بالای Notification مستقیماً به کلاس سطح پایین EmailSender وابسته است. اگه فردا بخوایم به جای ایمیل، با SMS اطلاع‌رسانی کنیم، مجبوریم کلاس Notification رو تغییر بدیم. این یعنی وابستگی سفت و سخت.
//  این کلاس سطح پایین است
public class EmailSender
{
public void Send() => Console.WriteLine("Email sent!");
}

// این کلاس سطح بالاست و مستقیماً به کلاس پایینی وابسته است
public class Notification
{
private readonly EmailSender _emailSender = new EmailSender();

public void SendNotification()
{
_emailSender.Send();
}
}


مثال خوب (رعایت اصل وارونگی وابستگی):
حالا با استفاده از یک Interface، این وابستگی رو "وارونه" می‌کنیم.

قدم اول: ساختن قرارداد (Interface)
این قرارداد در لایه سطح بالا تعریف میشه.
public interface IMessageSender
{
void SendMessage();
}

قدم دوم: کلاس‌های سطح پایین از قرارداد پیروی می‌کنند
public class EmailSender : IMessageSender
{
public void SendMessage() => Console.WriteLine("Email sent!");
}

public class SmsSender : IMessageSender
{
public void SendMessage() => Console.WriteLine("SMS sent!");
}

قدم سوم: کلاس سطح بالا به قرارداد وابسته است، نه به جزئیات
public class Notification
{
private readonly IMessageSender _sender;

// وابستگی از طریق Constructor تزریق می‌شود (Dependency Injection)
public Notification(IMessageSender sender)
{
_sender = sender;
}

public void SendNotification()
{
_sender.SendMessage();
}
}

جادو اینجا اتفاق میفته: حالا کلاس Notification دیگه کاری نداره که پیام چطوری ارسال میشه (با ایمیل یا SMS). اون فقط "قرارداد" رو می‌شناسه. ما می‌تونیم موقع ساختن آبجکت Notification، هر نوع IMessageSender که دوست داریم رو بهش پاس بدیم، بدون اینکه یک کلمه از کدش رو تغییر بدیم!

🤔 حرف حساب و تجربه شما
این DIP قلب معماری‌های تمیز و مدرنه و اساس کار تزریق وابستگی (Dependency Injection) هست. رعایت این اصل، کد شما رو فوق‌العاده انعطاف‌پذیر، قابل تست و توسعه‌پذیر می‌کنه.

شما چقدر به این اصل در پروژه‌هاتون اهمیت میدید؟ بهترین مثالی که از کاربرد این اصل تو ذهنتون دارید چیه؟

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #SOLID #SoftwareArchitecture #CleanCode #DIP
🛡 دستور using در #C: بهترین دوست IDisposable و راهی برای جلوگیری از نشت منابع
وقتی با فایل‌ها، دیتابیس، ارتباطات شبکه یا هر منبع خارجی دیگه‌ای کار می‌کنید، یه خطر بزرگ وجود داره: یادتون بره منابعی که باز کردید رو ببندید! این کار باعث "نشت منابع" (Resource Leaks) و مشکلات جدی در پرفورمنس و پایداری برنامه میشه.

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

1️⃣ مشکل کجاست؟ IDisposable و مدیریت منابع
بعضی از آبجکت‌ها در دات‌نت، منابعی رو مدیریت می‌کنن که Garbage Collector به صورت خودکار نمی‌تونه اون‌ها رو آزاد کنه (مثل دستگیره فایل در سیستم‌عامل). این کلاس‌ها، اینترفیس IDisposable رو پیاده‌سازی می‌کنن که فقط یک متد به اسم Dispose() داره.

وظیفه ما به عنوان برنامه‌نویس اینه که همیشه و تحت هر شرایطی، بعد از تموم شدن کارمون با این آبجکت‌ها، متد Dispose() اون‌ها رو صدا بزنیم.

2️⃣ راه حل قدیمی (و زشت): try...finally 👎
راه سنتی برای اینکه مطمئن بشیم Dispose() همیشه صدا زده میشه (حتی اگه وسط کار یه Exception رخ بده)، استفاده از بلوک try...finally هست:
StreamReader reader = null;
try
{
reader = new StreamReader("myFile.txt");
// ... کار کردن با فایل ...
}
finally
{
if (reader != null)
{
reader.Dispose(); // تضمین می‌کنه که فایل همیشه بسته میشه
}
}

این کد کار می‌کنه، ولی طولانی و زشته.

3️⃣ راه حل مدرن و شیک: دستور using
دستور using یه "شکر سینتکسی" (Syntactic Sugar) برای همون بلوک try...finally هست.

به محض اینکه اجرای کد از بلوک using خارج بشه (چه به صورت عادی و چه به خاطر یه Exception)، کامپایلر به صورت خودکار متد Dispose() رو روی اون آبجکت صدا می‌زنه. اینجوری کد شما خیلی تمیزتر، کوتاه‌تر و امن‌تر میشه.
// این کد دقیقاً معادل کد try...finally بالاست
using (StreamReader reader = new StreamReader("myFile.txt"))
{
// ... کار کردن با فایل ...
}
// reader.Dispose() اینجا به صورت خودکار در هر حالتی صدا زده میشه


4️⃣ فرم جدیدتر (از C# 8): using declarations 🚀
از C# 8 به بعد، کار حتی از این هم ساده‌تر شده. اگه متغیر using رو به این شکل تعریف کنید، دیگه نیازی به آکولاد {} ندارید و اون متغیر در انتهای اسکوپ فعلی (معمولاً در انتهای متد) به صورت خودکار Dispose میشه.
void ReadFile()
{
using var reader = new StreamReader("myFile.txt");
using var writer = new StreamWriter("log.txt");

// ... کار کردن با فایل‌ها ...

} // reader.Dispose() و writer.Dispose() اینجا به صورت خودکار صدا زده میشن


🤔 حرف حساب و قانون طلایی

قانون طلایی: هر کلاسی که IDisposable رو پیاده‌سازی کرده، باید داخل یه بلوک using (یا با سینتکس جدیدش) ازش استفاده بشه.

شما بیشتر از کدوم فرمت using استفاده می‌کنید؟ کلاسیک با براکت یا فرمت جدید بدون براکت؟

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #BestPractices #CleanCode #IDisposable
😵‍💫 برنامه‌نویس NET.؟

می‌خوای از باگ‌های دردناک، امنیت داغون و کد اسپاگتی در امان بمونی؟
این 10 قاتل خاموش رو دست‌کم نگیر!
(حتی تو پروژه‌های به‌ظاهر «Enterprise» هم می‌بینمشون…)



1️⃣ بدون اعتبارسنجی ورودی؟ خداحافظ با ثبات 😬

داده‌ی خراب بیاد تو، همه‌چی میریزه به هم.
پاک کردن داده‌ی خراب ۱۰ برابر سخت‌تر از جلوگیری از ورودشه!

🧱 همیشه ورودی رو چک کن →
Validate before trust



2️⃣ مقادیر هاردکد شده 🎯

عاشق سرتاسری Replace زدن تو پروژه‌ای؟
از «عدد جادویی» استفاده کن 😎
نه‌؟ پس برو سراغ:
🔸 فایل پیکربندی
🔸 ثابت‌ها
🔸 دیتابیس



3️⃣ وابستگی سفت و سخت بین کلاس‌ها 🔗

وقتی یه کلاس به کلاس دیگه دوخته شده باشه، انعطاف می‌ره هوا.
🙅‍♂️ با abstraction (مثل Interface) کدت رو قابل تغییر نگه دار.



4️⃣ تست واحد؟ وقت ندارم؟ 😐

اگه الان وقت نداری تست بنویسی،
فردا کلی وقت داری باگ‌هات رو دیباگ کنی! 🔥



5️⃣ مدیریت نکردن Exception ها 💣

اگه استک‌تریس کامل رو فرستادی تو پاسخ HTTP، یه کادو به هکر دادی!
📛 ارورها رو لاگ کن.
پیام امن بده به کاربر.



6️⃣ کد غیرقابل خوندن 🤯

واسه انسان بنویس نه ماشین!
اگه باید یه کد رو ۳ بار بخونی تا بفهمی چی می‌گه، خیلی پیچیده‌ست.

🧼 تمیز بنویس تا خودت ۳ ماه دیگه هم بفهمیش!



7️⃣ طراحی ضعیف دیتابیس 🐢

طرح دیتای اشتباه یعنی:
🔹 کندی
🔹 غیرقابل توسعه بودن
🔹 زجر در آینده

بلندمدت فکر کن موقع مدل‌سازی!



8️⃣ امنیت؟ بذار بعداً!

👾 این‌جوری هک می‌شی رفیق!
ورودی‌ها رو بررسی کن
کمترین سطح دسترسی
هرچی می‌اد رو پاکسازی کن (Sanitize)

امنیت چیز اختیاری نیست… هیچ‌وقت!



9️⃣ بدون لاگ و مانیتورینگ 🚫📊

برنامه رو منتشر کردی؟ دم‌ت گرم!
ولی حالا از کجا می‌فهمی داره درست کار می‌کنه؟
🕵️‍♂️ بدون لاگ = پرواز کور



🔟 اختراع دوباره چرخ؟ 😅

مگه قراره ORM اختراع کنی؟
تا وقتی یه ابزار تست‌شده و امن هست،
استفاده‌ش کن
🧠 وقتتو صرف چیزای ارزشمندتر کن!



🎯 لازم نیست کدت بی‌نقص باشه…

ولی اگه اینا رو نادیده بگیری،
کد Legacy درست کردی، نه پروژه حرفه‌ای!



🔖 هشتگ‌ها:
#DotNet #CSharp #CodingTips #BestPractices #Programming #SoftwareEngineering #DevLife
💾 حافظه کلاس‌ها در #C: راهنمای کامل Fields, readonly و const

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

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

1️⃣ فیلدها (Fields):

حافظه داخلی یک آبجکت فیلدها، متغیرهایی هستن که داخل یه کلاس یا struct تعریف میشن و "وضعیت" یا "داده"‌های اون آبجکت رو در طول عمرش نگه می‌دارن. هر نمونه (instance) از کلاس، یک کپی مستقل از فیلدهای خودش رو داره.

💡نکته حرفه‌ای (قرارداد نام‌گذاری):
یه قرارداد رایج و خوب، استفاده از آندرلاین (_) برای فیلدهای private هست تا به راحتی از متغیرهای محلی و پارامترها تشخیص داده بشن (مثلاً name_).
مقداردهی اولیه فیلدها:
مقداردهی اولیه به فیلدها اختیاریه. اگه مقداری بهشون ندید، مقدار پیش‌فرض نوعشون رو می‌گیرن. نکته مهم اینه که این مقداردهی قبل از اجرای اولین خط کد در سازنده (constructor) انجام میشه.

2️⃣ کلید readonly: فیلدهای فقط-خواندنی 🔒

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

قانون مهم: فیلدهای readonly فقط در دو جا می‌تونن مقدار بگیرن: یا موقع تعریف اولیه، یا داخل سازنده (constructor) اون کلاس.
public class UserProfile
{
// مقداردهی موقع تعریف
public readonly Guid UserId = Guid.NewGuid();

// تعریف بدون مقدار اولیه
public readonly DateTime RegistrationDate;

public UserProfile()
{
// مقداردهی در سازنده
RegistrationDate = DateTime.UtcNow;
}

public void UpdateProfile()
{
// UserId = Guid.NewGuid(); // خطای زمان کامپایل!
}
}


3️⃣ دوئل بزرگ: const در برابر static readonly ⚔️

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

🔵 const (ثابت زمان کامپایل):

• مقدارش باید در زمان کامپایل مشخص و ثابت باشه
(const double Pi = 3.14;).
• کامپایلر مقدارش رو مستقیماً در کد جایگزین می‌کنه (مثل ماکرو).
• فقط برای انواع داده ساده (عددی، رشته، بولین و...) قابل استفاده‌ست.

🔴 static readonly (ثابت زمان اجرا):

• مقدارش در زمان اجرا (معمولاً موقع استارت برنامه) مشخص میشه.
• یه فیلد واقعیه و در حافظه نگهداری میشه، مقدارش جایگزین نمیشه.
• برای هر نوع داده‌ای، حتی آبجکت‌های پیچیده، قابل استفاده‌ست.
public static readonly DateTime StartupTime = DateTime.Now;

😈تله خطرناک public const:

اگه شما یه public const رو در یک کتابخانه (Assembly A) تعریف کنید و در یک پروژه دیگه (Assembly B) ازش استفاده کنید، مقدار اون ثابت موقع کامپایل در Assembly B "پخته" یا "bake in" میشه. حالا اگه شما مقدار const رو در Assembly A عوض کنید، تا وقتی که Assembly B رو دوباره کامپایل نکنید، همچنان از همون مقدار قدیمی استفاده خواهد کرد! این می‌تونه منجر به باگ‌های فاجعه‌بار بشه. static readonly این مشکل رو نداره و همیشه آخرین مقدار رو می‌خونه، بنابراین انتخاب امن‌تریه.

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

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #OOP #CleanCode #BestPractices
🔬 کالبدشکافی متدها در #C: امضا (Signature) و Overloading

هر متدی در #C یک "اثر انگشت" یا امضای (Signature) منحصر به فرد داره. این امضا هویت متد رو مشخص می‌کنه و به کامپایلر اجازه میده بین چندین متد با اسم یکسان، تفاوت قائل بشه.

امروز می‌خوایم این مفهوم حیاتی و قوانین Overloading رو کالبدشکافی کنیم.

1️⃣ امضای متد (Method Signature) چیست؟ 🆔
امضای یک متد از دو بخش اصلی تشکیل شده:
• اسم متد
• نوع و ترتیب پارامترها

نکات کلیدی و تله‌ها: ⚠️
موارد زیر جزو امضای متد حساب نمی‌شن:

نوع خروجی (Return Type)

کلمه کلیدی params

اسم پارامترها (فقط نوع و ترتیبشون مهمه)

اما کلمات کلیدی ref و out جزو امضا حساب میشن!

2️⃣ اورلودینگ (Overloading): یک اسم، چند کاربرد 🎭

اورلودینگ یعنی شما می‌تونید چند متد با اسم یکسان در یک کلاس داشته باشید، به شرطی که امضاشون متفاوت باشه (یعنی تعداد، نوع یا ترتیب پارامترهاشون فرق کنه).

مثال Overloadهای معتبر:
// این‌ها همگی Overloadهای معتبری از Foo هستن
void Foo(int x) { }
void Foo(double x) { } // نوع پارامتر فرق داره
void Foo(int x, float y) { } // تعداد پارامترها فرق داره
void Foo(float x, int y) { } // ترتیب انواع پارامتر فرق داره
void Foo(ref int x) { } // وجود ref امضا رو تغییر میده


مثال Overloadهای نامعتبر:
//  خطای زمان کامپایل!
// چون فقط نوع خروجی فرق می‌کنه که جزو امضا نیست.
void Foo(int x) { }
float Foo(int x) { }

// خطای زمان کامپایل!
// چون params جزو امضا نیست.
void Goo(int[] x) { }
void Goo(params int[] x) { }

// خطای زمان کامپایل!
// ref و out نمی‌تونن تنها تفاوت امضا باشن.
void Another(ref int x) { }
void Another(out int x) { }


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

درک دقیق قوانین امضا و اورلودینگ، به شما کمک می‌کنه APIهای تمیز، خوانا و قابل فهمی طراحی کنید.

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #OOP #Methods #BestPractices
🛠 متدهای مدرن در #C
Expression-bodied و Local Methods

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

1️⃣ متدهای Expression-bodied (=>): خداحافظی با return و {}

اگه متد شما فقط از یک عبارت (Expression) تشکیل شده، دیگه نیازی به نوشتن بلوک {} و کلمه کلیدی return ندارید! می‌تونید با استفاده از "فت ارو" (=>)، اون رو در یک خط بنویسید.

این کار، کد شما رو فوق‌العاده تمیز و مینیمال می‌کنه.
// روش قدیمی
int Double(int x)
{
return x * 2;
}

// روش مدرن و شیک با Expression-bodied
int DoubleModern(int x) => x * 2;

// این قابلیت برای متدهای void هم کار می‌کنه
void SayHello() => Console.WriteLine("Hello!");


2️⃣ متدهای محلی (Local Methods): متد در دل متد!

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

مزایای این کار:

• کپسوله‌سازی عالی: اون متد کمکی، فقط همونجا قابل دسترسه و هیچ جای دیگه‌ای از کلاس رو آلوده نمی‌کنه.

• دسترسی به متغیرهای محلی: متد محلی می‌تونه به متغیرهای محلی و پارامترهای متد بیرونی دسترسی داشته باشه.
void WriteCubes()
{
Console.WriteLine(Cube(3));
Console.WriteLine(Cube(4));

// این متد، فقط داخل WriteCubes قابل دسترسه
int Cube(int value) => value * value * value;
}


💡نکته حرفه‌ای (static local methods):
از C# 8 به بعد، اگه متد محلی شما نیازی به دسترسی به متغیرهای متد بیرونی نداره، می‌تونید اون رو با کلمه کلیدی static تعریف کنید. این کار به کامپایلر کمک می‌کنه بهینه‌سازی‌های بهتری انجام بده و جلوی دسترسی‌های ناخواسته رو هم می‌گیره.

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

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

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #CleanCode #ModernCSharp #BestPractices
🏗 سازنده‌ها (Constructors) در #C: معمار آبجکت‌های شما

هر آبجکتی در #C یه "لحظه تولد" داره. اون لحظه، کدی اجرا میشه که آبجکت رو برای زندگی آماده می‌کنه. به این کد جادویی میگن سازنده (Constructor).

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

1️⃣ سازنده چیست و چطور کار می‌کند؟

سازنده شبیه یک متده، با این تفاوت که اسمش دقیقاً هم‌اسم خود کلاس هست و هیچ نوع خروجی‌ای (حتی void) نداره. کار اصلیش، مقداردهی اولیه فیلدها و آماده‌سازی آبجکته.
public class Panda
{
string _name; // فیلد

// این سازنده است
public Panda(string name)
{
_name = name; // کد مقداردهی اولیه
}
}

// ... نحوه استفاده
Panda p = new Panda("Petey"); // سازنده اینجا صدا زده میشه


💡نکته حرفه‌ای: برای سازنده‌های تک‌خطی، می‌تونید از سینتکس Expression-bodied استفاده کنید:
public Panda(string name) => _name = name;
ترفند this: اگه اسم پارامتر با اسم فیلد یکی بود، می‌تونید با کلمه کلیدی this به فیلد کلاس اشاره کنید:
public Panda(string name) => this.name = name;

2️⃣ اورلودینگ و زنجیره‌ای کردن سازنده‌ها (this):

شما می‌تونید چندین سازنده با ورودی‌های مختلف (Overloading) داشته باشید. برای جلوگیری از تکرار کد، یک سازنده می‌تونه اون یکی رو با کلمه کلیدی : this(...) صدا بزنه.
public class Wine
{
public decimal Price;
public int Year;

public Wine(decimal price)
{
Price = price;
}

// این سازنده، قبل از اجرای بدنه خودش، سازنده بالایی رو صدا میزنه
public Wine(decimal price, int year) : this(price)
{
Year = year;
}
}


3️⃣ تله‌ی سازنده پیش‌فرض! ⚠️

قانون مهم: کامپایلر #C فقط و فقط زمانی که شما هیچ سازنده‌ای در کلاس تعریف نکرده باشید، یه سازنده عمومی بدون پارامتر ( ()public MyClass) براتون میسازه.

به محض اینکه شما حتی یک سازنده (با یا بدون پارامتر) بنویسید، اون سازنده اتوماتیک حذف میشه و اگه بهش نیاز دارید، باید خودتون دستی بنویسیدش. این یکی از خطاهای رایج برای تازه‌کارهاست!

4️⃣ ترتیب اجرا: اول فیلدها، بعد سازنده

اگه فیلدهاتون مقدار اولیه دارن، این مقداردهی همیشه قبل از اجرای اولین خط کد در سازنده و به ترتیب تعریفشون در کلاس انجام میشه.
class Player
{
int shields = 50; // این اول اجرا میشه
int health = 100; // این دوم اجرا میشه

public Player()
{
// این سوم اجرا میشه
Console.WriteLine("Constructor executed!");
}
}


5️⃣ کاربرد حرفه‌ای: سازنده‌های private

چرا باید یه سازنده رو private کنیم؟ برای اینکه کنترل کامل ساخت آبجکت رو به دست بگیریم! این الگو (که بهش Factory Method میگن) به ما اجازه میده که منطق ساخت رو داخل یه متد استاتیک قرار بدیم. مثلا برای پیاده‌سازی الگوی Singleton یا برگردوندن آبجکت از یک Pool.
public class MyApiClien
{
// سازنده خصوصیه، پس کسی از بیرون نمی‌تونه new کنه
private MyApiClient() { }

// فقط از طریق این متد استاتیک میشه نمونه ساخت
public static MyApiClient Create()
{
// ... منطق پیچیده برای ساخت و کانفیگ ...
return new MyApiClient();
}
}

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #OOP #Constructor #BestPractices
ساخت آبجکت مثل یک حرفه‌ای: قدرت Object Initializers در #C


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

سی‌شارپ یه راه حل خیلی شیک، مدرن و امن برای این کار داره: Object Initializers.

1️⃣ روش سنتی در برابر روش مدرن
فرض کنید این کلاس Bunny رو داریم:
public class Bunny
{
public string Name;
public bool LikesCarrots;
public bool LikesHumans;

public Bunny() {}
public Bunny(string n) => Name = n;
}

روش قدیمی و چند خطی: 👎
Bunny b1 = new Bunny();
b1.Name = "Bo";
b1.LikesCarrots = true;
b1.LikesHumans = false;

روش مدرن با Object Initializer: 👍
حالا با سینتکس {}، می‌تونیم تمام این کارها رو در یک دستور و به صورت خیلی خوانا انجام بدیم:
Bunny b2 = new Bunny 
{
Name = "Bo",
LikesCarrots = true,
LikesHumans = false
};


این قابلیت حتی با سازنده‌هایی که پارامتر دارن هم کار می‌کنه:
Bunny b3 = new Bunny("Bo") 
{
LikesCarrots = true,
LikesHumans = false
};


2️⃣ پشت صحنه چه خبره؟ (نکته حرفه‌ای) ⚙️
شاید فکر کنید این سینتکس فقط یه خلاصه نویسیه، ولی کامپایلر پشت صحنه یه کار هوشمندانه برای امنیت در برابر خطاها (Exception Safety) انجام میده.

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #OOP #CleanCode #BestPractices
🔬 کالبدشکافی آبجکت‌ها با Deconstructors در #C


تو پست قبلی دیدیم چطور با Object Initializers یه آبجکت رو به صورت شیک "بسازیم". حالا بیاید ببینیم چطور می‌تونیم یه آبجکت رو به همون زیبایی "بشکافیم" و اجزاش رو استخراج کنیم!

سی‌شارپ یه قابلیت مدرن و قدرتمند به اسم Deconstructor داره که دقیقاً برعکس سازنده (Constructor) عمل می‌کنه.

1️⃣ حالا Deconstructor چیست؟
این Deconstructor یه متد خاص به اسم Deconstruct هست که شما تو کلاستون تعریف می‌کنید. این متد، فیلدها و پراپرتی‌های کلاس شما رو به مجموعه‌ای از متغیرهای خروجی (out parameters) تبدیل می‌کنه.
public class Rectangle
{
public readonly float Width, Height;

public Rectangle(float width, float height)
{
Width = width;
Height = height;
}

// این متد Deconstructor ماست
public void Deconstruct(out float width, out float height)
{
width = Width;
height = Height;
}
}


2️⃣ جادوی سینتکس: کالبدشکافی در یک خط!
حالا که متد Deconstruct رو داریم، #C به ما یه سینتکس فوق‌العاده شیک و خوانا برای استفاده ازش میده:
var rect = new Rectangle(3, 4);

// جادو اینجا اتفاق میفته!
// این خط، متد Deconstruct رو صدا میزنه
(float width, float height) = rect;

Console.WriteLine($"Width: {width}, Height: {height}"); // خروجی: Width: 3, Height: 4
این سینتکس، کد شما رو به شدت تمیز و بیانگر می‌کنه.


3️⃣ ترفندهای خلاصه‌نویسی
این قابلیت چند تا ترفند برای خلاصه‌تر شدن هم داره:

استفاده از var:
// کامپایلر خودش نوع‌ها رو تشخیص میده
var (width, height) = rect;

نادیده گرفتن با _ (Discard):
اگه فقط به یکی از مقادیر نیاز دارید، می‌تونید اون یکی رو با _ نادیده بگیرید:
// ما اینجا فقط به ارتفاع نیاز داریم
var (_, height) = rect;

تخصیص به متغیرهای موجود:
اگه متغیرها رو از قبل دارید، دیگه نیازی به تعریفشون نیست:
float w, h;
(w, h) = rect;

🤔 حرف حساب و تجربه شما
شما تا حالا از Deconstructors تو کدهاتون استفاده کردید؟ به نظرتون بهترین کاربرد این قابلیت کجاست؟

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #ModernCSharp #CleanCode #BestPractices
جمع‌بندی 📝
معرفی فیلترهای کوئری نام‌دار در EF 10 یکی از محدودیت‌های دیرینه را برطرف می‌کند. شما اکنون می‌توانید:

🔹 چندین فیلتر را به یک انتیتی متصل کرده و آن‌ها را به صورت جداگانه مدیریت کنید.

🔹 فیلترهای خاصی را در یک کوئری LINQ با استفاده از IgnoreQueryFilters(["FilterName"]) به صورت انتخابی غیرفعال کنید.

🔹 الگوهای رایجی مانند حذف منطقی و چند-مستأجری را ساده‌سازی کنید.

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

آن‌ها را در نسخه پیش‌نمایش امتحان کنید و به این فکر کنید که چگونه می‌توانند پایگاه کد شما را ساده‌تر کنند.

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #EntityFrameWork #EF
💡 نکته عملکردی C#/.NET – آرایه‌های Inline 🔥


💎 آرایه‌های Inline چیستند؟

⚡️ در C# 12 و NET 8.0. معرفی شده‌اند. آرایه‌های inline به ما اجازه می‌دهند که یک آرایه با اندازه ثابت در یک نوع ساختاری (struct) ایجاد کنیم. این آرایه‌ها توسط تیم Runtime و نویسندگان دیگر کتابخانه‌ها برای بهبود عملکرد در برنامه‌های شما استفاده می‌شوند.

⚡️ از نظر عملکرد در کنسول، تغییر خاصی در کارکرد ایجاد نشده است. یک struct با یک آرایه inline باید ویژگی‌های عملکردی مشابه یک بافر ثابت (fixed size buffer) ناایمن (unsafe) داشته باشد.

💡 برخلاف آرایه‌های پویا (dynamic) سنتی، آرایه‌های inline در فضای حافظه همان struct قرار می‌گیرند. این جای‌گیری منحصربه‌فرد چند مزیت کلیدی را فراهم می‌کند.

چند مزیت آرایه‌های Inline:

🔸 بهبود عملکرد: با حذف تخصیص حافظه روی heap و استفاده از حافظه stack، آرایه‌های inline سرعت اجرای توابع را به شکل قابل‌توجهی افزایش می‌دهند و فشار کلی روی حافظه را کاهش می‌دهند.
🔸 مدیریت حافظه ساده‌تر: دیگر نیازی به تخصیص صریح یا نگرانی درباره جمع‌آوری زباله (Garbage Collection) نیست. آرایه‌های inline به‌طور یکپارچه در structها ادغام می‌شوند و شما را از دردسر مدیریت حافظه رها می‌کنند.
🔸 ایمنی نوع قوی‌تر: بررسی‌های زمان کامپایل برای اندازه آرایه و نوع عناصر، یک لایه حفاظتی اضافی در برابر خطاهای زمان اجرا ایجاد می‌کنند.

🔖هشتگ‌ها:
#csharp #dotnet #programming #softwareengineering #softwaredevelopment
🚀 جادوی async/await در #C:

برنامه‌نویسی غیرهمزمان به زبان ساده
تا حالا شده یه دکمه تو اپلیکیشن‌تون بزنید و کل برنامه برای چند ثانیه هنگ کنه و سفید بشه؟ 🥶 این اتفاق وقتی میفته که یه کار زمان‌بر (مثل دانلود فایل یا کوئری دیتابیس) رو به صورت همزمان (Synchronous) انجام میدید و "نخ" اصلی برنامه رو قفل می‌کنید.

راه حل این کابوس، برنامه‌نویسی غیرهمزمان (Asynchronous) با دو کلمه کلیدی جادویی async و await هست.

1️⃣ داستان سرآشپز صبور (آنالوژی) 👨‍🍳

برای درک این مفهوم، یه رستوران رو تصور کنید:

سرآشپز همزمان (Synchronous): 👎
شما سفارش استیک میدید. سرآشپز استیک رو روی گریل میذاره و همونجا وایمیسته و ۱۰ دقیقه بهش زل میزنه تا بپزه. تو این ۱۰ دقیقه، هیچ کار دیگه‌ای نمی‌تونه بکنه و بقیه مشتری‌ها گشنه می‌مونن. این یعنی قفل شدن برنامه!

سرآشپز غیرهمزمان (Asynchronous): 👍
شما سفارش استیک میدید. سرآشپز استیک رو روی گریل میذاره (await) و بلافاصله از آشپزخونه میاد بیرون و سفارش بقیه رو میگیره. اون یه "قول" (Task) داره که استیک در حال آماده شدنه. ۱۰ دقیقه بعد، وقتی استیک آماده شد، برمی‌گرده سراغش، کار رو تموم می‌کنه و به شما تحویل میده. تو این مدت، رستوران (برنامه) کاملاً فعال و پاسخگو بوده!

2️⃣ کلمات کلیدی جادویی: async, await, Task

این سه تا با هم کار می‌کنن:

• async:
یه برچسبه که به متد می‌زنیم و به کامپایلر میگیم: "هی، این متد ممکنه وسط کارش منتظر یه چیزی بمونه و غیرهمزمانه". این کلمه، اجازه استفاده از await رو داخل متد میده.

• Task / Task<T>:
"قول" یا "رسیدی" هست که متد async فوراً برمی‌گردونه.

• Task:
یعنی "قول میدم این کار رو تموم کنم." (برای متدهایی که خروجی ندارن).

• Task<T>:
یعنی "قول میدم این کار رو تموم کنم و یه نتیجه از نوع T بهت تحویل بدم."

• await:
قلب ماجراست! این کلمه رو قبل از صدا زدن یه متد async دیگه میذاریم و به برنامه میگه:

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

3️⃣ مثال عملی: دانلود کردن یک فایل

روش بد (Synchronous) که باعث هنگ کردن برنامه میشه:
//  این متد نخ اصلی رو برای ۵ ثانیه قفل می‌کنه!
public void DownloadFile()
{
Thread.Sleep(5000); // شبیه‌سازی یک عملیات زمان‌بر و مسدودکننده
Console.WriteLine("Download complete.");
}


روش خوب (Asynchronous) با async/await:
//  این متد نخ اصلی رو آزاد می‌کنه و برنامه پاسخگو باقی می‌مونه
public async Task DownloadFileAsync()
{
// await کنترل رو به بیرون برمی‌گردونه و منتظر می‌مونه
await Task.Delay(5000); // شبیه‌سازی یک عملیات غیرهمزمان
Console.WriteLine("Download complete.");
}

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #Async #Await #Concurrency
📌در این مثال:

• کلید کش برای هر محصول منحصر به فرد است.

• اگر محصول در کش باشد، بلافاصله برگردانده می‌شود.

• اگر نباشد، متد factory برای گرفتن داده اجرا می‌شود.

• درخواست‌های همزمان دیگر برای همان محصول، منتظر پایان یافتن اولین درخواست می‌مانند.

تنظیم مستقیم ورودی‌های کش ✍️

گاهی اوقات نیاز دارید کش را مستقیماً به‌روزرسانی کنید، مانند پس از تغییر داده‌ها. متد SetAsync این کار را انجام می‌دهد:
app.MapPut("/products/{id}", async (int id, Product product, HybridCache cache) =>
{
// ابتدا دیتابیس را به‌روزرسانی کنید
await UpdateProductInDatabase(product);

// سپس کش را با انقضای سفارشی به‌روزرسانی کنید
var options = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromHours(1),
LocalCacheExpiration = TimeSpan.FromMinutes(30)
};

await cache.SetAsync(
$"product-{id}",
product,
options
);

return Results.NoContent();
});


استفاده از تگ‌های کش 🏷

تگ‌ها برای مدیریت گروه‌هایی از ورودی‌های کش مرتبط، قدرتمند هستند. شما می‌توانید چندین ورودی را به یکباره با استفاده از تگ‌ها نامعتبر کنید:
app.MapGet("/categories/{id}/products", async (...) =>
{
var tags = [$"category-{id}", "products"];

var products = await cache.GetOrCreateAsync(
$"products-by-category-{id}",
async token => { /* ... fetch products ... */ },
tags: tags,
cancellationToken: ct
);

return Results.Ok(products);
});

// Endpoint برای نامعتبر کردن تمام محصولات در یک دسته‌بندی
app.MapPost("/categories/{id}/invalidate", async (id, cache, ct) =>
{
await cache.RemoveByTagAsync($"category-{id}", ct);
return Results.NoContent();
});


📍تگ‌ها برای موارد زیر مفید هستند:


• نامعتبر کردن تمام محصولات در یک دسته‌بندی.

• پاک کردن تمام داده‌های کش شده برای یک کاربر خاص.

• رفرش کردن تمام داده‌های مرتبط هنگامی که چیزی تغییر می‌کند.

حذف ورودی‌های تکی 🗑

برای نامعتبرسازی مستقیم آیتم‌های خاص، از RemoveAsync استفاده کنید:
app.MapDelete("/products/{id}", async (int id, HybridCache cache) =>
{
// ابتدا از دیتابیس حذف کنید
await DeleteProductFromDatabase(id);

// سپس از کش حذف کنید
await cache.RemoveAsync($"product-{id}");

return Results.NoContent();
});


افزودن Redis به عنوان کش L2 🔥

برای استفاده از Redis به عنوان کش توزیع‌شده خود:
پکیج NuGet را نصب کنید:

Install-Package Microsoft.Extensions.Caching.StackExchangeRedis
Redis و HybridCache را پیکربندی کنید:

// افزودن Redis
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "your-redis-connection-string";
});
// افزودن HybridCache - به طور خودکار از Redis به عنوان L2 استفاده خواهد کرد
builder.Services.AddHybridCache();


خلاصه 📝

HybridCache
کشینگ را در اپلیکیشن‌های NET. ساده می‌کند. این قابلیت، کشینگ سریع درون-حافظه‌ای را با کشینگ توزیع‌شده ترکیب می‌کند، از مشکلات رایج مانند cache stampede جلوگیری می‌کند، و هم در سیستم‌های تک-سروری و هم توزیع‌شده به خوبی کار می‌کند.

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

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #HybridCache
📖 سری آموزشی کتاب C# 12 in a Nutshell

👇کلیدواژه this در #C:

'خود' آبجکت کیست؟ در دنیای شیءگرایی، گاهی وقتا یه آبجکت نیاز داره به "خودش" اشاره کنه. ابزار #C برای این کار، کلمه کلیدی ساده ولی قدرتمند this هست. this در واقع ضمیر "من" برای یک آبجکته و به نمونه فعلی (current instance) خودش اشاره می‌کنه.

1️⃣ کاربرد اول: رفع ابهام (Disambiguation)
این رایج‌ترین کاربرد this هست. وقتی اسم پارامتر سازنده، هم‌اسم یکی از فیلدهای کلاس باشه، برای اینکه به کامپایلر بفهمونیم منظورمون فیلد کلاسه، از this استفاده می‌کنیم.
public class Test
{
private string name;
public Test(string name)
{
// this.name به فیلد کلاس اشاره داره
// name به پارامتر ورودی اشاره داره
this.name = name;
}
}


2️⃣ کاربرد دوم: پاس دادن خودِ آبجکت 🤝
گاهی وقتا لازمه یه آبجکت، رفرنس خودش رو به یه آبجکت یا متد دیگه بده.
public class Panda
{
public Panda Mate;
public void Marry(Panda partner)
{
Mate = partner;
// 'خودم' رو به عنوان جفتِ شریکم معرفی می‌کنم
partner.Mate = this;
}
}


قانون مهم ⚠️

this
فقط در اعضای غیر استاتیک (non-static) یک کلاس یا struct معتبره.

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #DotNet #OOP #ThisKeyword
📖 سری آموزشی کتاب C# 12 in a Nutshell

🏦 پراپرتی‌ها (Properties) در #C:

دروازه‌های هوشمند کلاس شما چرا تو کدنویسی حرفه‌ای، تقریباً هیچوقت فیلدهای یه کلاس رو public نمی‌کنن؟ چون این کار یعنی از دست دادن کنترل! هر کسی از بیرون می‌تونه هر مقدار نامعتبری رو توش بریزه.

راه حل #C برای این مشکل، یه قابلیت فوق‌العاده به اسم پراپرتی (Property) هست.

1️⃣ پراپرتی چیست؟ فیلد با ماسک متد! 🎭

پراپرتی‌ها از بیرون شبیه فیلدهای معمولی به نظر میرسن و به همون سادگی استفاده میشن، ولی در داخل، در واقع متدهای خاصی هستن که بهشون اکسسور (accessor) گفته میشه. این به ما کنترل کامل روی خوندن و نوشتن مقدار رو میده.
Stock msft = new Stock();
msft.CurrentPrice = 30; // اکسسور set صدا زده میشه

msft.CurrentPrice -= 3;

Console.WriteLine(msft.CurrentPrice); // اکسسور get صدا زده میشه


2️⃣ کالبدشکافی یک پراپرتی 🔬

در رایج‌ترین حالت، یک پراپرتی از دو بخش تشکیل شده:

• فیلد پشتیبان (Backing Field): یک فیلد private که داده واقعی رو نگه میداره.

• پراپرتی public: دروازه‌ای که به دنیای بیرون اجازه دسترسی کنترل‌شده به اون فیلد رو میده.

✨️این پراپرتی، دو اکسسور داره:

🔹️get:
وقتی پراپرتی رو می‌خونیم، این بلوک اجرا میشه.

🔹️set:
وقتی مقداری رو به پراپرتی اختصاص میدیم، این بلوک اجرا میشه. کلمه کلیدی value در اینجا، به مقداری که داره ست میشه، اشاره داره.
public class Stock
{
// ۱. فیلد پشتیبان (private)
private decimal _currentPrice;
// ۲. پراپرتی عمومی (public)
public decimal CurrentPrice
{
get { return _currentPrice; }
set { _currentPrice = value; }
}
}


3️⃣ قدرت واقعی: کپسوله‌سازی (Encapsulation) 🛡

جادوی پراپرتی‌ها اینجاست که می‌تونید تو اکسسورهای get و set، منطق دلخواهتون رو پیاده کنید. مثلاً اعتبارسنجی (validation).
public class Stock
{
private decimal _currentPrice;
public decimal CurrentPrice
{
get { return _currentPrice; }
set
{
// منطق اعتبارسنجی
if (value < 0)
{
throw new ArgumentException("Price cannot be negative!");
}
_currentPrice = value;
}
}
}


🤔 حرف حساب و قانون طلایی
قانون طلایی شیءگرایی: فیلدها رو همیشه private نگه دارید و با پراپرتی‌های public اون‌ها رو در معرض دید بذارید. این کار به شما کنترل کامل روی کلاس‌هاتون میده و اساس کپسوله‌سازیه.

🔖 هشتگ‌ها:
#CSharp #Programming #DotNet #OOP #Properties #Encapsulation
📖 سری آموزشی کتاب C# 12 in a Nutshell
🚀 تکنیک‌های حرفه‌ای با Primary Constructors در 12 #C

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

امروز می‌خوایم با این ترفندها و البته محدودیت‌هاشون آشنا بشیم.

1️⃣ مقداردهی مستقیم فیلدها و پراپرتی‌ها
شما می‌تونید پارامترهای سازنده اصلی رو مستقیماً برای مقداردهی اولیه فیلدها و پراپرتی‌های عمومی استفاده کنید. این کار نیاز به نوشتن کد انتساب تکراری در یک سازنده سنتی رو حذف می‌کنه.
class Person(string firstName, string lastName)
{
// پارامتر firstName مستقیماً به فیلد عمومی FirstName اختصاص داده میشه
public readonly string FirstName = firstName;
// پارامتر lastName مستقیماً به پراپرتی عمومی LastName اختصاص داده میشه
public string LastName { get; } = lastName;
}


2️⃣ ماسک کردن (Masking) و تغییرناپذیری
یه تکنیک جالب، تعریف یه فیلد readonly با همون اسم پارامتره. در این حالت، فیلد، پارامتر اصلی رو "ماسک" می‌کنه. این کار یه راه ساده برای اطمینان از اینه که مقدار اولیه، بعد از ساخت آبجکت دیگه تغییر نمی‌کنه و به صورت داخلی readonly باقی می‌مونه.
class Person(string firstName, string lastName)
{
// این فیلدها، پارامترهای ورودی رو ماسک می‌کنن
readonly string firstName = firstName;
readonly string lastName = lastName.ToUpper(); // حتی می‌تونیم روشون عملیات هم انجام بدیم!
public void Print() => Console.WriteLine(firstName + " " + lastName);
}


3️⃣ اعتبارسنجی (Validation) در لحظه تولد! 🛡
قدرت اصلی اینجاست! شما می‌تونید منطق اعتبارسنجی رو مستقیماً در مقداردهی اولیه فیلدها پیاده کنید. با استفاده از "throw expressions"، می‌تونیم کد خیلی تمیزی برای چک کردن null یا مقادیر نامعتبر بنویسیم.
class Person(string firstName, string lastName)
{
// اگه lastName نال باشه، همینجا یه Exception پرتاب میشه
readonly string lastName = lastName ?? throw new ArgumentNullException(nameof(lastName));
public void Print() => Console.WriteLine(firstName + " " + lastName);
}

// new Person("Alice", null); // throws ArgumentNullException


4️⃣ محدودیت مهم: پراپرتی‌های خواندنی/نوشتنی ⚠️
با تمام این قدرت، Primary Constructors یه محدودیت مهم دارن. اگه بخواید یه پراپرتی خواندنی/نوشتنی ({ get; set; }) با منطق اعتبارسنجی داشته باشید، کار پیچیده میشه. چون باید اون منطق رو هم در مقداردهی اولیه و هم در اکسسور set تکرار کنید.

در این سناریو، برگشتن به روش سازنده سنتی و صریح معمولاً راه حل تمیزتریه.

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

Primary Constructors
یه ابزار عالی برای سناریوهای ساده و کلاس‌های تغییرناپذیره، ولی مثل هر ابزار دیگه‌ای، باید بدونیم کجا ازش استفاده کنیم و محدودیت‌هاش رو بشناسیم.

🔖 هشتگ‌ها:
#CSharp #DotNet #CSharp12 #Programming #Developer #OOP
📖 سری آموزشی کتاب C# 12 in a Nutshell

🏗 تقسیم کدهای بزرگ با partial در #C: کلاس‌ها و متدهای چندتکه

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

سی‌شارپ برای این کار یه راه حل عالی و تمیز داره: کلمه کلیدی partial.

1️⃣ کلاس‌های Partial:

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

مهم‌ترین کاربرد: جداسازی کدهای دست‌نویس شما از کدهای اتوماتیک.

فایل ۱ (اتوماتیک): PaymentForm.g.cs
// این بخش توسط یک ابزار ساخته شده
public partial class PaymentForm
{
// ... کنترل‌های دیزاینر و کدهای اتوماتیک
}

فایل ۲ (دست‌نویس): PaymentForm.cs
// این بخش رو شما می‌نویسید
public partial class PaymentForm
{
// ... منطق و ایونت‌های مربوط به فرم
}


2️⃣ متدهای Partial: قلاب‌های جادویی که ناپدید میشن! 🎩

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

💡نکته جادویی: اگه شما هیچ پیاده‌سازی‌ای براش ارائه ندید، کامپایلر هم تعریف و هم تمام فراخوانی‌های اون متد رو از کد نهایی حذف می‌کنه! این یعنی هیچ هزینه پرفورمنسی نداره.

فایل ۱ (اتوماتیک):
public partial class PaymentForm
{
public void Submit()
{
// یه قلاب برای اعتبارسنجی قبل از ارسال
ValidatePayment(this.Amount);
// ...
}
// تعریف متد partial (بدون بدنه)
partial void ValidatePayment(decimal amount);
}

فایل ۲ (دست‌نویس):
public partial class PaymentForm
{
// پیاده‌سازی متد partial
partial void ValidatePayment(decimal amount)
{
if (amount > 1000)
{
// ... منطق اعتبارسنجی ...
}
}
}

3️⃣ متدهای Partial توسعه‌یافته (از 9 #C) 🚀

این نسخه جدیدتر، برای کار با Source Generatorها طراحی شده. در این حالت، شما تعریف متد رو می‌نویسید و انتظار دارید که Source Generator بدنه اون رو تولید کنه. این متدها دیگه اختیاری نیستن و باید پیاده‌سازی بشن و می‌تونن خروجی و پارامتر out هم داشته باشن.

🔖 هشتگ‌ها:
#CSharp #Programming #DotNet #CleanCode #Partial
Forwarded from Brain bytes
### E) Event-Driven Paradigm
Flow controlled by events rather than sequential commands.

public class Button
{
public event Action? Click;
public void OnClick() => Click?.Invoke();
}

var button = new Button();
button.Click += () => Console.WriteLine("Button clicked!");
button.OnClick();


Used in UI, messaging systems, reactive pipelines.

---

### F) Asynchronous Paradigm
Handle I/O or long-running tasks without blocking threads.

public async Task<string> FetchAsync()
{
using var http = new HttpClient();
return await http.GetStringAsync("https://example.com");
}

var data = await FetchAsync();
Console.WriteLine(data);


Combines async/await with Task for clearer concurrency.

---

### G) Reactive (Optional Extension)
Treat data as streams (e.g. with IObservable): react declaratively to change over time.

---

## 4) How C# Programming Model Enables These Paradigms

| Paradigm | Model Elements (C#) |
|---------------|---------------------|
| Imperative | loops, mutable locals, branching (if, switch) |
| OOP | class, interface, abstract, virtual, override, access modifiers |
| Functional | lambdas, delegates (Func<>, Action), LINQ, record types |
| Declarative | LINQ query syntax, attributes, expression trees |
| Event-Driven | event, delegates, EventHandler, UI frameworks |
| Asynchronous | async, await, Task, CancellationToken, ValueTask |
| Reactive | observables (via libraries), continuation chains |

C# is multi-paradigm: mix domain modeling (OOP) + data transformations (functional/declarative) + async I/O + events.

---

## 5) Choosing a Paradigm (Quick Guide)

| Situation | Best Fit |
|-----------|----------|
| Rich domain entities, lifecycle | OOP |
| Data querying/filtering | Declarative (LINQ) |
| Composable transformations, testability | Functional style |
| UI interactions, user input | Event-Driven |
| Network / file / database latency | Asynchronous |
| Simple scripts / procedural tasks | Imperative |
| Live data streams / continuous updates | Reactive |

Often you combine several in one solution.

---

## 6) Summary
Paradigm = How you think and structure the solution conceptually.
Programming Model = The language/runtime mechanisms enabling those structures.
C# provides a unified model supporting multiple paradigms seamlessly.

---

## 7) Glossary (English Term + Persian Meaning)

| Term | Persian |
|------|--------|
| Programming Paradigm | پارادایم برنامه‌نویسی / سبک مفهومی |
| Programming Model | مدل برنامه‌نویسی / مکانیزم اجرایی |
| Imperative | دستوری |
| Declarative | اعلامی / деклараتی |
| Object-Oriented (OOP) | شیءگرا |
| Encapsulation | کپسوله‌سازی |
| Inheritance | ارث‌بری |
| Polymorphism | چندریختی |
| Abstraction | انتزاع |
| Class | کلاس |
| Object | شیء |
| Method | متد |
| State | حالت |
| Functional Programming | برنامه‌نویسی تابعی |
| Pure Function | تابع خالص |
| Side Effect | عارضهٔ جانبی |
| Immutability | تغییرناپذیری |
| Lambda Expression | عبارت لامبدا |
| Delegate | نماینده (تابع اشاره‌ای) |
| LINQ | چارچوب کوئری یکپارچه |
| Query Syntax | نحوهٔ نگارش کوئری |
| Expression Tree | درخت بیان |
| Event | رویداد |
| Event-Driven | رویدادمحور |
| Asynchronous / Async | ناهمگام |
| Concurrency | همزمانی |
| Task | وظیفهٔ ناهمگام |
| CancellationToken | توکن لغو |
| Record | رکورد (نوع دادهٔ مختصر) |
| Virtual | مجازی (قابل بازنویسی) |
| Override | بازنویسی |
| Abstract | انتزاعی |
| Interface | اینترفیس / قرارداد |
| Reactive | واکنشی |
| Multi-Paradigm | چندپارادایمی |
| API | رابط برنامه‌نویسی کاربردی |
| Design Pattern | الگوی طراحی |
| Refactoring | بازآرایی کد |
| Maintainability | نگهداشت‌پذیری |
| Scalability | مقیاس‌پذیری |
| Deferred Execution | اجرای مؤخر |
| DSL | زبان دامنه‌محور |
| Idempotent | ایدمپوتنت (تکرار بدون تغییر نتیجه) |

---

## 8) Tags
#programming #paradigm #programming_model #CSharp #OOP #Functional #Declarative #LINQ #Async #EventDriven #Reactive #DotNet #SoftwareDesign #CleanCode #BrainBytes #Architecture #Coding #Developer
Entity Framework Extensions 💎

آیا می‌توانیم بهتر از SqlBulkCopy عمل کنیم؟
شاید، حداقل نتایج بنچمارک من نشان می‌دهد که می‌توانیم.

یک کتابخانهٔ فوق‌العاده دیگر به نام Entity Framework Extensions وجود دارد. این فقط یک کتابخانهٔ bulk insert نیست - بنابراین توصیه می‌کنم حتماً بررسی شود. با این حال، امروز آن را برای bulk insert استفاده خواهیم کرد.

برای استفادهٔ ما، متد BulkInsertOptimizedAsync گزینهٔ عالی است. می‌توانیم کالکشن آبجکت‌ها را ارسال کنیم و یک SQL bulk insert انجام خواهد شد. همچنین برخی بهینه‌سازی‌ها زیر هود انجام می‌دهد تا عملکرد بهتر شود.
using var context = new ApplicationDbContext();

await context.BulkInsertOptimizedAsync(GetUsers());

عملکرد آن فوق‌العاده است: ⚡️🔥
EF Core - Entity Framework Extensions، برای ۱۰۰ کاربر: ۱.۸۶ ms
EF Core - Entity Framework Extensions، برای ۱,۰۰۰ کاربر: ۶.۹ ms
EF Core - Entity Framework Extensions، برای ۱۰,۰۰۰ کاربر: ۶۶ ms
EF Core - Entity Framework Extensions، برای ۱۰۰,۰۰۰ کاربر: ۶۳۶ ms
EF Core - Entity Framework Extensions، برای ۱,۰۰۰,۰۰۰ کاربر: ۷,۱۰۶ ms


جمع‌بندی 🎯

کار SqlBulkCopy برای حداکثر سرعت و سادگی بهترین است. 👑
با این حال، Entity Framework Extensions عملکرد فوق‌العاده‌ای ارائه می‌دهند و هم‌زمان سهولت استفاده‌ای که EF Core دارد را حفظ می‌کنند. 💎⚡️

بهترین گزینه به نیازهای خاص پروژهٔ شما بستگی دارد:
فقط عملکرد مهم است؟ SqlBulkCopy راه حل شماست. 🔥

به سرعت عالی و توسعهٔ آسان نیاز دارید؟ EF Core انتخاب هوشمندانه است. ⚡️

به دنبال تعادل بین عملکرد و سهولت استفاده هستید؟ Entity Framework Extensions ⚖️

تصمیم با شماست که بهترین گزینه برای پروژهٔ خودتان کدام است.

امیدوارم مفید بوده باشد. 🙌

🔖هشتگ‌ها:
#EFCore #Dapper #SqlBulkCopy #BulkExtensions #EntityFrameworkExtensions #Performance #CSharp #Database #DotNet #Programming #BulkInsert