C# Geeks (.NET)
334 subscribers
128 photos
1 video
98 links
Download Telegram
🛡 سیاست تخصیص قطعی در #C: چرا کامپایلر از شما باهوش‌تر است؟
تا حالا براتون سوال شده چرا گاهی اوقات اگه به یه متغیر مقدار اولیه ندید، کامپایلر ازتون ایراد میگیره، ولی گاهی اوقات خودش بهش مقدار صفر یا null میده؟

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

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

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

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

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


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

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


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

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

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

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

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

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

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

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

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

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

کلمه کلیدی default

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

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

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


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

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

Point p = default;

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


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

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

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

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

🔖 هشتگ‌ها :
#CSharp
#CodingTips
#SoftwareEngineering
⚙️ الفبای منطق در #C :
عبارت‌ها (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
😵‍💫 برنامه‌نویس 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#/.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
📊 Benchmark

برای اثبات اینکه این روش واقعاً کار می‌کند، یک برنامه کوچک NET 10. با Aspire و PostgreSQL ساختم.
چون همه‌چیز روی سیستم محلی اجرا می‌شد، زمان‌ها خیلی پایین‌اند؛
اما اگر دیتابیس ریموت بود، اعداد بزرگ‌تر می‌شدند — نسبتِ سرعت (Speedup Ratio) تقریباً همین می‌مانَد.

🐢 اجرای ترتیبی (Sequential Execution): حدود ۳۶ms

در حالت ترتیبی، دقیقاً یک Waterfall داریم:
هر Query منتظر تمام‌شدن Query قبلی می‌مانَد.

یعنی:
Query 1 → تمام شود → Query 2 → تمام شود → Query 3

این ساختار از لحاظ تجربهٔ کاربری، فوق‌العاده کند است.

⚡️ اجرای موازی (Parallel Execution): حدود ۱۳ms

با رویکرد موازی‌سازی:
تمام Query ها هم‌زمان شروع می‌شوند و تقریباً هم‌زمان به پایان می‌رسند.

نتیجه:
۳ برابر سریع‌تر
(در این مثال: ۳۶ms → ۱۳ms)

این همان جایی است که تاخیرهای شبکه، I/O و latency دیتابیس را به‌صورت مؤثری کاهش می‌دهیم. 🚀

⚖️ ملاحظات، Trade-off ‌ها و نتیجه‌گیری

استفاده از IDbContextFactory پلی است بین:
معماری EF Core که بر واحد کار (Unit of Work) و Context واحد طراحی شده و نیازهای مدرن که اجرای موازی حقیقی را می‌طلبد.

این الگو به شما اجازه می‌دهد از جعبهٔ
"یک درخواست → یک Thread → یک DbContext"
خارج شوید — بدون اینکه Thread-Safety یا Data Integrity قربانی شود. ✔️

اما باید با احتیاط استفاده شود:

⚠️ 1️⃣ احتمال اتمام Connection Pool

وقتی درخواست قبلاً فقط ۱ Connection مصرف می‌کرد،
در حال حاضر همان درخواست ۳ Connection می‌گیرد.

اگر ترافیک بالایی داشته باشید و connection pool کوچک باشد:
ممکن است سریعاً Connection Exhaustion رخ دهد.
این یعنی درخواست‌ها در صف می‌مانند یا Timeout می‌دهند. ❗️

⚠️ 2️⃣ سربار Context

اگر Query های شما بسیار سریع هستند (lookup ساده بر اساس ID)،
ساختن چندین Task و DbContext جدید
ممکن است حتی کندتر از حالت ترتیبی شود!

این روش مناسب Query های سنگین‌تر و پنجره‌های بزرگ داده است—not simple queries. ⚙️

🧠 نکتهٔ پایانی

وقتی با یک Dashboard کند مواجه شدید،
قبل از اینکه سراغ SQL دستی یا Stored Procedure بروید…

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

🔖هشتگ‌ها:
#EFCore #ParallelProgramming
#AsyncAwait #SoftwareEngineering #IDbContextFactory