💡 نکته عملکردی 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 این کار را انجام میدهد:
تگها برای مدیریت گروههایی از ورودیهای کش مرتبط، قدرتمند هستند. شما میتوانید چندین ورودی را به یکباره با استفاده از تگها نامعتبر کنید:
• نامعتبر کردن تمام محصولات در یک دستهبندی.
• پاک کردن تمام دادههای کش شده برای یک کاربر خاص.
• رفرش کردن تمام دادههای مرتبط هنگامی که چیزی تغییر میکند.
برای نامعتبرسازی مستقیم آیتمهای خاص، از RemoveAsync استفاده کنید:
برای استفاده از Redis به عنوان کش توزیعشده خود:
پکیج NuGet را نصب کنید:
Install-Package Microsoft.Extensions.Caching.StackExchangeRedis
Redis و HybridCache را پیکربندی کنید:
HybridCache
کشینگ را در اپلیکیشنهای NET. ساده میکند. این قابلیت، کشینگ سریع درون-حافظهای را با کشینگ توزیعشده ترکیب میکند، از مشکلات رایج مانند cache stampede جلوگیری میکند، و هم در سیستمهای تک-سروری و هم توزیعشده به خوبی کار میکند.
با تنظیمات پیشفرض و الگوهای استفاده اولیه شروع کنید - این کتابخانه طوری طراحی شده که استفاده از آن ساده باشد در حالی که مشکلات پیچیده کشینگ را حل میکند.
• کلید کش برای هر محصول منحصر به فرد است.
• اگر محصول در کش باشد، بلافاصله برگردانده میشود.
• اگر نباشد، متد 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
'خود' آبجکت کیست؟ در دنیای شیءگرایی، گاهی وقتا یه آبجکت نیاز داره به "خودش" اشاره کنه. ابزار #C برای این کار، کلمه کلیدی ساده ولی قدرتمند this هست. this در واقع ضمیر "من" برای یک آبجکته و به نمونه فعلی (current instance) خودش اشاره میکنه.
1️⃣ کاربرد اول: رفع ابهام (Disambiguation)
این رایجترین کاربرد this هست. وقتی اسم پارامتر سازنده، هماسم یکی از فیلدهای کلاس باشه، برای اینکه به کامپایلر بفهمونیم منظورمون فیلد کلاسه، از this استفاده میکنیم.
2️⃣ کاربرد دوم: پاس دادن خودِ آبجکت 🤝
گاهی وقتا لازمه یه آبجکت، رفرنس خودش رو به یه آبجکت یا متد دیگه بده.
this
فقط در اعضای غیر استاتیک (non-static) یک کلاس یا struct معتبره.
👇کلیدواژه 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
دروازههای هوشمند کلاس شما چرا تو کدنویسی حرفهای، تقریباً هیچوقت فیلدهای یه کلاس رو public نمیکنن؟ چون این کار یعنی از دست دادن کنترل! هر کسی از بیرون میتونه هر مقدار نامعتبری رو توش بریزه.
راه حل #C برای این مشکل، یه قابلیت فوقالعاده به اسم پراپرتی (Property) هست.
پراپرتیها از بیرون شبیه فیلدهای معمولی به نظر میرسن و به همون سادگی استفاده میشن، ولی در داخل، در واقع متدهای خاصی هستن که بهشون اکسسور (accessor) گفته میشه. این به ما کنترل کامل روی خوندن و نوشتن مقدار رو میده.
در رایجترین حالت، یک پراپرتی از دو بخش تشکیل شده:
• فیلد پشتیبان (Backing Field): یک فیلد private که داده واقعی رو نگه میداره.
• پراپرتی public: دروازهای که به دنیای بیرون اجازه دسترسی کنترلشده به اون فیلد رو میده.
✨️این پراپرتی، دو اکسسور داره:
🔹️get:
وقتی پراپرتی رو میخونیم، این بلوک اجرا میشه.
🔹️set:
وقتی مقداری رو به پراپرتی اختصاص میدیم، این بلوک اجرا میشه. کلمه کلیدی value در اینجا، به مقداری که داره ست میشه، اشاره داره.
جادوی پراپرتیها اینجاست که میتونید تو اکسسورهای get و set، منطق دلخواهتون رو پیاده کنید. مثلاً اعتبارسنجی (validation).
🤔 حرف حساب و قانون طلایی
قانون طلایی شیءگرایی: فیلدها رو همیشه private نگه دارید و با پراپرتیهای public اونها رو در معرض دید بذارید. این کار به شما کنترل کامل روی کلاسهاتون میده و اساس کپسولهسازیه.
🏦 پراپرتیها (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 آشنا شدیم. اما قدرت واقعی این قابلیت، در تکنیکهای پیشرفتهتریه که به شما اجازه میده کدهای خیلی تمیزتر و هوشمندتری بنویسید.
امروز میخوایم با این ترفندها و البته محدودیتهاشون آشنا بشیم.
1️⃣ مقداردهی مستقیم فیلدها و پراپرتیها
شما میتونید پارامترهای سازنده اصلی رو مستقیماً برای مقداردهی اولیه فیلدها و پراپرتیهای عمومی استفاده کنید. این کار نیاز به نوشتن کد انتساب تکراری در یک سازنده سنتی رو حذف میکنه.
2️⃣ ماسک کردن (Masking) و تغییرناپذیری
یه تکنیک جالب، تعریف یه فیلد readonly با همون اسم پارامتره. در این حالت، فیلد، پارامتر اصلی رو "ماسک" میکنه. این کار یه راه ساده برای اطمینان از اینه که مقدار اولیه، بعد از ساخت آبجکت دیگه تغییر نمیکنه و به صورت داخلی readonly باقی میمونه.
3️⃣ اعتبارسنجی (Validation) در لحظه تولد! 🛡
قدرت اصلی اینجاست! شما میتونید منطق اعتبارسنجی رو مستقیماً در مقداردهی اولیه فیلدها پیاده کنید. با استفاده از "throw expressions"، میتونیم کد خیلی تمیزی برای چک کردن null یا مقادیر نامعتبر بنویسیم.
4️⃣ محدودیت مهم: پراپرتیهای خواندنی/نوشتنی ⚠️
با تمام این قدرت، Primary Constructors یه محدودیت مهم دارن. اگه بخواید یه پراپرتی خواندنی/نوشتنی ({ get; set; }) با منطق اعتبارسنجی داشته باشید، کار پیچیده میشه. چون باید اون منطق رو هم در مقداردهی اولیه و هم در اکسسور set تکرار کنید.
در این سناریو، برگشتن به روش سازنده سنتی و صریح معمولاً راه حل تمیزتریه.
Primary Constructors
یه ابزار عالی برای سناریوهای ساده و کلاسهای تغییرناپذیره، ولی مثل هر ابزار دیگهای، باید بدونیم کجا ازش استفاده کنیم و محدودیتهاش رو بشناسیم.
🚀 تکنیکهای حرفهای با 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.
یک کلاس در چند فایل کلمه کلیدی partial به شما اجازه میده تعریف یک کلاس، struct یا اینترفیس رو در چند فایل مختلف تقسیم کنید. کامپایلر موقع کامپایل، تمام این تیکهها رو به هم میچسبونه و به عنوان یک کلاس واحد در نظر میگیره.
مهمترین کاربرد: جداسازی کدهای دستنویس شما از کدهای اتوماتیک.
فایل ۱ (اتوماتیک): PaymentForm.g.cs
فایل ۲ (دستنویس): PaymentForm.cs
این قابلیت به شما اجازه میده در یک بخش از کلاس (معمولاً کد اتوماتیک)، یک "قلاب" یا تعریف متد بدون بدنه بذارید. بعداً در بخش دیگه کلاس (کد دستنویس)، میتونید اون متد رو پیادهسازی کنید.
💡نکته جادویی: اگه شما هیچ پیادهسازیای براش ارائه ندید، کامپایلر هم تعریف و هم تمام فراخوانیهای اون متد رو از کد نهایی حذف میکنه! این یعنی هیچ هزینه پرفورمنسی نداره.
فایل ۱ (اتوماتیک):
فایل ۲ (دستنویس):
این نسخه جدیدتر، برای کار با Source Generatorها طراحی شده. در این حالت، شما تعریف متد رو مینویسید و انتظار دارید که Source Generator بدنه اون رو تولید کنه. این متدها دیگه اختیاری نیستن و باید پیادهسازی بشن و میتونن خروجی و پارامتر out هم داشته باشن.
🏗 تقسیم کدهای بزرگ با 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.
Used in UI, messaging systems, reactive pipelines.
---
### F) Asynchronous Paradigm
Handle I/O or long-running tasks without blocking threads.
Combines
---
### 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 (
| OOP |
| Functional | lambdas, delegates (
| Declarative | LINQ query syntax, attributes, expression trees |
| Event-Driven |
| Asynchronous |
| 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
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