Software Philosophy
3.46K subscribers
163 photos
42 videos
1.57K links
چکیده‌ای از مفاهیم به روز مهندسی نرم افزار برای مهندسین نرم‌افزار.
معماری نوین نرم‌افزار، تکنولوژی‌های برنامه نویسی جدید
Download Telegram
ایندکسر (Indexer) در سی‌شارپ

#csharp_for_beginners

وقتی یک کلاس یا ساختار (struct) را می‌سازیم، ممکن است بخواهیم از آن مانند آرایه‌ای با “[]” به موقعیت‌های کلاس یا ساختار دسترسی داشت: هم خواندن و هم نوشتن. ایندکسرها این امکان را فراهم می‌کنند. یعنی به جای روش‌های معمول مثل GetItem(…) یا SetItem(…)، بتوان نوشت:
myObject[i] = value;
var x = myObject[i];

ساختار ایندکسر

ایندکسر شبیه پراپرتی تعریف می‌شود، با این تفاوت که زمان get و set یک یا چند پارامتر (معمولاً اندیس) دریافت می‌کند. برای تعریف ایندکسر از کلمه‌ی کلیدی this استفاده می‌کنیم:
public class SampleCollection<T>
{
private T[] arr = new T[100];

public T this[int i]
{
get { return arr[i]; }
set { arr[i] = value; }
}

انواع ایندکسر
خواندنی و نوشتنی (Read/Write): هم get و هم set را داراست.
فقط خواندنی (Read-only): فقط get را داراست. مثلاً اگر لازم باشد فقط به داده‌ها دسترسی دهیم ولی تغییری در داده‌ها ندهیم.
چند پارامتری: ایندکسر می‌تواند بیشتر از یک ایندکس داشته باشد، مانند ایندکسر دو بعدی
غیر عددی: الزامی نیست شاخص‌ها عدد باشند؛ می‌اتونند نوعی مانند رشته، تاریخ یا هر نوع دلخواهی باشند.

موارد استفاده
شبیه‌سازی آرایه یا لیست: وقتی کلاس شما مانند یک مجموعه عمل می‌کند، ولی نمی‌خواهید جزئیات داخلی را بیرون دهید.
دیکشنری / نگاشت (mapping): مثلاً وقتی می‌خواهید بر اساس کلید (مانند رشته یا تاریخ) مقدار دهی کنید یا مقداری را بگیرید، بجای متدهایی مانند Get یا Find، می‌توانید بنویسید: obj[“key”] .
داده‌های وابسته به زمان یا تاریخ: مانند ثبت دما بر اساس تاریخ، طوری که بتوانید با obj[date] بخوانید یا بنویسید.
زمانی که نمی‌خواهیم کل داده‌ها به صورت همزمان در حافظه داشته باشیم: ممکن است بخش‌هایی از داده را بر حسب نیاز بارگذاری یا حذف کنید. ایندکسر اجازه می‌دهد که فقط وقتی به داده‌ای نیاز داریم، آن قسمت پردازش شود.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
👍4❤3
اجرای کدهای پایتون در دات‌نت با جادوی CSnakes!

اگر امکان اجرای کدهای پایتون در همان پروسس دات‌نت وجود داشته باشد، یعنی تمام ۱.۵ میلیون مدل هوش مصنوعی که تا به حال روی HuggingFace قرار گرفته را می‌توان با همان پرفورمنس و بدون نیاز به کشیدن لایه‌های REST در دسترس داشت.

پروژه CSnakes در واقع یک Source Generator و Runtime برای سی‌شارپ است که با بهره‌گیری از Python C-API امکان تولید خودکار کلاس‌های دات‌نت از اسکریپت‌های پایتون رو فراهم می‌کنه. شما فقط کافیه پکیج CSnakes.Runtime رو از NuGet نصب کنید و اسکریپت‌های پایتون‌تون رو به پروژه اضافه کنید تا بدون کوچک‌ترین overhead یا لایه اضافی، هر تابع پایتون به‌صورت یک متد native سی‌شارپ قابل فراخوانی باشد. این رویکرد، سرعت و مقیاس‌پذیری Enterprise دات‌نت را با انعطاف‌پذیری و اکوسیستم غنی پایتون پیوند می‌زند و توسعه اپلیکیشن‌های هوش‌مصنوعی و Data Science را به سطحی جدید می‌رساند.

کل‌کل‌هایی هم که این دونفر سر زبان‌های سی‌شارپ و پایتون می‌کنن خیلی با مزه‌س!

🔗 در این ویدئو Scott Hanselman و Anthony Shaw پروژه CSnakes را معرفی می‌کنند. پیشنهاد می‌کنم حتما این ویدئوی جذاب را ببینید.


#csharp #python #machine_learning

#مهران_داودی (لینکدین - بلاگ)

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
❤10👍10🔥2👏1😱1
رابط (Interface) در سی‌شارپ

#csharp_for_beginners

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

از نسخه سی‌شارپ ۱۱ به بعد interface می‌تواند اعضای static abstract یا static virtual داشته باشد. این موضوع زمانی مفید است که بخواهیم در یک نوع عمومی (generic) رفتار مشخصی برای تمام انواع پیاده‌ساز اجباری کنیم. به عنوان مثال در کتابخانه دات‌نت انواع عددی مختلف واسط INumber را پیاده می‌کنند تا عملیات ریاضی مشترک میان آنها تضمین شود.

قوانین دسترسی و سطح تعریف
یک interface سطح بالا (در فضای نام) می‌تواند internal یا public باشد. پیش‌فرض internal است.
اگر interface به صورت تو در تو داخل یک نوع دیگر تعریف شود می‌توان از هر نوع اصلاح‌کننده دسترسی استفاده کرد.
اعضای interface که بدون پیاده‌سازی هستند اصلاح‌کننده دسترسی ندارند. اما اگر برای آن عضو پیاده‌سازی پیش‌فرض بنویسیم می‌توان دسترسی آن را مشخص کرد.


انواع اعضا در interface
یک interface می‌تواند شامل موارد زیر باشد:
-متدها
-ویژگی‌ها
-ایندکسرها
-رویدادها
-ثابت‌ها
-عملگرها
-انواع تو در تو
-سازنده ایستا

پیاده‌سازی
یک interface می‌تواند از یک یا چند interface دیگر مشتق شود. هر نوعی که interface مشتق را پیاده کند باید تمام اعضای interfaceهای پایه و مشتق را پیاده‌سازی کند.
کلاس یا ساختار می‌تواند اعضای interface را به صورت ضمنی یا به صورت صریح (explicit implementation) پیاده کند.
اگر یک عضو interface پیاده‌سازی پیش‌فرض داشته باشد معمولاً تنها از طریق نمونه‌ای از نوع interface قابل دسترسی است نه مستقیماً از طریق کلاس پیاده‌ساز.

مثال‌ها

تعریف یک قرارداد ساده

interface ISampleInterface
{
void SampleMethod();
}

class ImplementationClass : ISampleInterface
{
void ISampleInterface.SampleMethod()
{
// پیاده‌سازی متد
}
}


تعریف ویژگی‌ها و متدها

interface IPoint
{
int X { get; set; }
int Y { get; set; }
double Distance { get; }
}

class Point : IPoint
{
public int X { get; set; }
public int Y { get; set; }
public double Distance => Math.Sqrt(X * X + Y * Y);
}



🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
👍2
اپراتورها در سی‌شارپ

#csharp_for_beginners

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

دسته‌های اصلی اپراتورها
۱. اپراتورهای حسابی: برای انجام محاسبات ریاضی مثل جمع، تفریق، ضرب، تقسیم و باقی‌مانده استفاده می‌شوند.
۲. اپراتورهای مقایسه‌ای: برای مقایسه دو مقدار به‌کار می‌روند، مثل بزرگ‌تر، کوچک‌تر یا برابر بودن.
۳. اپراتورهای منطقی بولی: برای ترکیب و معکوس کردن مقادیر درست و نادرست (true/false) استفاده می‌شوند.
۴. اپراتورهای بیت‌به‌بیت و شیفت: برای کار روی بیت‌های داخلی داده‌های عددی کاربرد دارند.
۵. اپراتورهای برابری: برای بررسی مساوی یا نامساوی بودن دو مقدار استفاده می‌شوند.
۶. اپراتورهای انتساب و ترکیبی: برای مقداردهی متغیرها یا ترکیب یک عملیات با انتساب به‌کار می‌روند، مانند += یا -=.
۷. اپراتور شرطی سه‌تایی: یک عبارت شرطی است که بین دو مقدار یکی را انتخاب می‌کند.
۸. اپراتورهای Null: برای بررسی نال بودن و جایگزین کردن مقدار پیش‌فرض استفاده می‌شوند.
۹. اپراتورهای دسترسی به عضو، ایندکس، افزایش یا کاهش و تبدیل نوع: برای دسترسی به اعضای یک شیء، کار با آرایه‌ها، افزایش/کاهش مقدار یا تبدیل نوع داده به نوع دیگر استفاده می‌شوند.

اولویت و جهت اجرای اپراتورها
اپراتورها در سی‌شارپ اولویت‌های مختلفی دارند. اپراتورهایی با اولویت بالاتر زودتر اجرا می‌شوند. اگر چند اپراتور در یک سطح اولویت باشند، ترتیب اجرا توسط جهت ارجاع مشخص می‌شود. اکثر اپراتورهای دوتایی از چپ به راست اجرا می‌شوند، اما برخی مانند انتساب و اپراتور شرطی از راست به چپ اجرا می‌شوند.
به‌عنوان مثال، عبارت a + b - c به‌صورت (a + b) - c محاسبه می‌شود، ولی عبارت x = y = z به شکل x = (y = z) ارزیابی خواهد شد

ترتیب ارزیابی عملوندها
به‌طور پیش‌فرض، عملوندهای یک اپراتور از چپ به راست محاسبه می‌شوند. با این حال، برخی اپراتورها شرطی هستند و ممکن است همه عملوندها محاسبه نشوند.
• در اپراتور && اگر عملوند سمت چپ برابر false باشد، سمت راست دیگر بررسی نمی‌شود.
• در اپراتور || اگر عملوند سمت چپ true باشد، سمت راست اجرا نمی‌شود.
• در اپراتور ?? یا ??=، اگر مقدار سمت چپ نال نباشد، سمت راست محاسبه نمی‌شود.
• در اپراتور شرطی سه‌تایی ?: فقط یکی از شاخه‌ها اجرا می‌شود.
• در عملگرهای شرطی نال مانند ?. یا ?[]، اگر شیء سمت چپ نال باشد، ادامه‌ی عبارت متوقف می‌شود

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
👍8❤1🔥1
ساختارها در سی‌شارپ

#csharp_for_beginners

ساختار یا struct نوعی value type در زبان سی‌شارپ است که برای نگهداری داده‌ها و رفتار مرتبط با آن‌ها استفاده می‌شود.
وقتی متغیری از نوع struct ساخته می‌شود، داده‌ها مستقیماً درون آن متغیر ذخیره می‌شوند، نه در یک شیء جداگانه در heap.
در نتیجه، وقتی یک struct به متد ارسال یا از متد بازگردانده می‌شود، کل مقدار آن کپی می‌گردد.
به همین دلیل، struct برای انواع داده‌ای کوچک و مستقل مناسب است.
در مقابل، اگر نوعی داده رفتار پیچیده یا اندازه‌ی بزرگ دارد، معمولاً کلاس گزینه‌ی بهتری است.

مثال ساده از تعریف ساختار

public struct Coords
{
public Coords(double x, double y)
{
X = x
Y = y
}

public double X { get }
public double Y { get }

public override string ToString() => $"({X}, {Y})"
}



یک نوع دیگر به نام readonly struct & readonly

می‌توان یک ساختار را با کلیدواژه readonly تعریف کرد تا تغییرناپذیر باشد.
در یک readonly struct تمام فیلدها باید readonly باشند و تمام ویژگی‌ها (properties) باید فقط getter داشته باشند یا از نوع init باشند. در این حالت ساختار دیگر قابل تغییر نیست و اطمینان حاصل می‌شود که داده‌ها پس از ساخت ثابت باقی می‌مانند.

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

مثال از readonly struct

public readonly struct Coords
{
public Coords(double x, double y)
{
X = x
Y = y
}

public double X { get; init; }
public double Y { get; init; }

public readonly override string ToString() => $"({X}, {Y})"
}


آرایه‌های درون‌خطی (inline arrays)

از نسخه‌ی سی‌شارپ ۱۲ به بعد، امکان تعریف آرایه‌های درون‌خطی در قالب struct فراهم شده است. در این نوع ساختار، فقط یک فیلد داخلی وجود دارد که شامل یک بلوک پیوسته از عناصر داده است. این ویژگی برای موقعیت‌هایی که نیاز به سرعت بالا و دسترسی سریع به حافظه وجود دارد مفید است.

مقداردهی اولیه و مقدار پیش‌فرض struct

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

اگر برای ساختار سازنده‌ی بدون پارامتر تعریف شود، باز هم دستور default آن را فراخوانی نمی‌کند و مقدار پیش‌فرض برای هر فیلد اعمال می‌شود.
از سی‌شارپ ۱۱ به بعد اگر سازنده مقداری برای فیلدها تعیین نکند، کامپایلر به صورت خودکار آن‌ها را با مقدار پیش‌فرض مقداردهی می‌کند.

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



🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
👍5
تعریف Enum

#csharp_for_beginners

یک Enum در واقع نوع داده‌ای سفارشی است که مجموعه‌ای از ثابت‌های عددی نام‌گذاری‌شده را در خود نگه می‌دارد. برای مثال:

enum Season
{
Spring,
Summer,
Autumn,
Winter
}


در اینجا، اعضا به ترتیب دارای مقادیر عددی 0، 1، 2 و 3 هستند. نوع پایه‌ی Enum به‌صورت پیش‌فرض int است، اما می‌توان آن را تغییر داد.

تعیین نوع پایه و مقادیر صریح


می‌توان نوع پایه و مقادیر اعضا را به‌صورت دستی مشخص کرد:

enum ErrorCode : ushort
{
None = 0,
Unknown = 1,
ConnectionLost = 100,
OutlierReading = 200
}


در این مثال، نوع پایه ushort است و هر عضو مقدار خاص خود را دارد.

نکات مهم در استفاده از Enum
مقدار پیش‌فرض یک Enum برابر با عدد صفر است، حتی اگر هیچ عضوی با مقدار صفر تعریف نشده باشد.

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

کاربردهای Enum

۱. انتخاب از میان چند مقدار مشخص
یک Enum زمانی مفید است که بخواهیم متغیری یکی از چند مقدار مشخص را بگیرد. مثلاً برای وضعیت سفارش یا فصل سال:

enum OrderStatus
{
Pending,
Processing,
Shipped,
Delivered
}


۲. استفاده به‌صورت ترکیبی (Flags)
گاهی لازم است چند مقدار با هم ترکیب شوند. در این حالت از ویژگی [Flags] استفاده می‌کنیم و مقادیر را به‌صورت توان‌های دو تعریف می‌کنیم:

[Flags]
public enum Days
{
None = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 4,
Thursday = 8,
Friday = 16,
Saturday = 32,
Sunday = 64,
Weekend = Saturday | Sunday
}



جمع‌بندی
ابزار Enum یکی از ابزارهای ساده اما قدرتمند در سی‌شارپ است که به شما کمک می‌کند مجموعه‌ای از مقادیر ثابت را با نام‌های قابل فهم تعریف کنید. این کار باعث افزایش خوانایی، کاهش خطا و بهبود نگهداری کد می‌شود. با رعایت چند قاعده‌ی ساده —مثل داشتن عضو صفر، اعتبارسنجی مقادیر و استفاده‌ی درست از [Flags]— می‌توان Enumهایی ساخت که در پروژه‌های واقعی بسیار کاربردی و ایمن باشند.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
👍9❤3
کلاس لیست (List)

#csharp_for_beginners

کلاس «لیست» یا List در فضای نام System.Collections.Generic قرار دارد و یکی از پرکاربردترین ساختارهای داده در چارچوب ‎.NET است. این کلاس نمایان‌گر مجموعه‌ای از عناصر هم‌نوع (دارای نوع مشخص) است که می‌توان به هر کدام از آن‌ها از طریق شماره‌ی ایندکس دسترسی داشت.
علاوه بر این، کلاس لیست امکاناتی برای افزودن، حذف، جستجو، مرتب‌سازی و مدیریت داده‌ها در اختیار برنامه‌نویس قرار می‌دهد.

پارامتر نوع
لیست از نوع عمومی (Generic) است و دارای پارامتری به نام T می‌باشد.
این پارامتر مشخص می‌کند که نوع داده‌ای که قرار است در لیست نگهداری شود چیست (مثلاً عدد صحیح، رشته، شیء و غیره).

سازنده‌ها (ایجادکننده‌های لیست)
کلاس لیست چند روش برای ساخت شیء جدید ارائه می‌دهد:
سازنده‌ی بدون ورودی: یک لیست خالی با ظرفیت اولیه‌ی پیش‌فرض می‌سازد.
سازنده‌ای که ورودی آن یک مجموعه است: از عناصر مجموعه‌ی داده شده، یک لیست جدید می‌سازد.
سازنده‌ای که عدد صحیح می‌گیرد: لیستی خالی با ظرفیت اولیه‌ی مشخص‌شده ایجاد می‌کند.

ویژگی‌های اصلی لیست
• ظرفیت (Capacity): تعداد کل عناصری که لیست می‌تواند بدون تغییر اندازه در خود جای دهد.
• تعداد (Count): تعداد واقعی عناصری که در حال حاضر در لیست وجود دارند.
• اندیس (Item): اجازه می‌دهد تا با استفاده از شماره‌ی اندیس، به یک عنصر دسترسی پیدا کرده یا مقدار آن را تغییر دهیم.

متدهای مهم در لیست
کلاس لیست دارای ده‌ها متد کاربردی است. در ادامه مهم‌ترین آن‌ها آورده شده است

افزودن (Add): یک عنصر جدید را به انتهای لیست اضافه می‌کند.
افزودن مجموعه‌ای از عناصر (AddRange): چندین عنصر را به انتهای لیست اضافه می‌کند.
فقط‌خواندنی (AsReadOnly): نمایی فقط برای خواندن از لیست ایجاد می‌کند که قابل تغییر نیست.
جستجوی دودویی (BinarySearch): با استفاده از الگوریتم جستجوی دودویی، عنصری را در لیست مرتب‌شده پیدا می‌کند.
پاک‌کردن (Clear): همه‌ی عناصر موجود در لیست را حذف می‌کند.
شامل بودن (Contains): بررسی می‌کند که آیا یک عنصر خاص در لیست وجود دارد یا نه.
کپی کردن (CopyTo): عناصر لیست را در آرایه‌ای دیگر کپی می‌کند.
افزایش ظرفیت (EnsureCapacity): اطمینان حاصل می‌کند که ظرفیت لیست به اندازه‌ی کافی برای اضافه شدن عناصر جدید وجود دارد.
وجود شرطی (Exists): بررسی می‌کند آیا عنصری مطابق یک شرط مشخص در لیست وجود دارد یا نه.
یافتن اولین مورد (Find): اولین عنصری که با شرط داده‌شده مطابقت دارد را برمی‌گرداند.
یافتن همه‌ی موارد (FindAll): تمام عناصری که شرط را برآورده می‌کنند بازمی‌گرداند.
یافتن اندیس (FindIndex / FindLastIndex): موقعیت اولین یا آخرین عنصر مطابق شرط را برمی‌گرداند.
برای هر عنصر (ForEach): عملی را روی تمام عناصر اجرا می‌کند.
دریافت بازه (GetRange): بخش مشخصی از لیست را به‌صورت یک لیست جدید برمی‌گرداند.
درج (Insert / InsertRange): عنصری یا مجموعه‌ای از عناصر را در موقعیت مشخصی از لیست قرار می‌دهد.
حذف (Remove): اولین وقوع یک عنصر مشخص را حذف می‌کند.
حذف شرطی (RemoveAll): همه‌ی عناصری که شرط خاصی را برآورده می‌کنند حذف می‌کند.
حذف بر اساس اندیس (RemoveAt / RemoveRange): عنصری در یک موقعیت یا بازه‌ای از عناصر را حذف می‌کند.
معکوس‌کردن (Reverse): ترتیب عناصر را برعکس می‌کند، می‌تواند کل لیست یا بخشی از آن باشد.
مرتب‌سازی (Sort): عناصر را به ترتیب صعودی یا بر اساس مقایسه‌کننده‌ی دلخواه مرتب می‌کند.
تبدیل به آرایه (ToArray): عناصر لیست را در قالب یک آرایه بازمی‌گرداند.
بهینه‌سازی حافظه (TrimExcess): ظرفیت لیست را به تعداد واقعی عناصر کاهش می‌دهد تا از مصرف بی‌مورد حافظه جلوگیری شود.
بررسی شرط برای همه (TrueForAll): بررسی می‌کند آیا همه‌ی عناصر شرط مشخصی را برآورده می‌کنند یا خیر.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
❤6👍1
تاپل‌ها در سی‌شارپ

#csharp_for_beginners

در زبان برنامه‌نویسی سی‌شارپ، از نسخه‌های جدید‌تر مفهومی با نام تاپل‌ها معرفی شده است؛ این امکان فراهم می‌کند که چند مقدار مرتبط را به‌صورت کم‌حجم و منسجم در کنار هم نگه‌دارید. به‌طور خاص، این مقاله به نوع داده‌ای به نام «تاپل مقدار» (value-tuple) می‌پردازد که در سند رسمی مایکروسافت تحت عنوان «Tuple types (C# reference)» معرفی شده است.

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

(double, int) t1 = (4.5, 3);
Console.WriteLine($"Tuple with elements {t1.Item1} and {t1.Item2}.");


برابری (Tuple equality)ها چگونه مقایسه می‌شوند

تاپل‌ها از عملگرهای == و != پشتیبانی می‌کنند؛ این مقایسه اعضای متناظر (به ترتیب) را با اپراتور مقایسه انجام می‌دهد. نام فیلدها در مقایسه دخیل نیستند؛ به همین دلیل دو تاپل با نام‌های متفاوت اما همان ترتیب و مقادیر، برابر در نظر گرفته می‌شوند.

مثال صفحه

(int a, byte b) left = (5, 10);
(long a, int b) right = (5, 10);
Console.WriteLine(left == right); // True


نام‌گذاری فیلدهای تاپل (Tuple field names)، جزئیات مهم

نحوهٔ تعیین نام فیلدها
نام فیلدها را می‌توان صریحاً هنگام مقداردهی یا در تعریف نوع تاپل مشخص کرد:

var t = (Sum: 4.5, Count: 3);
Console.WriteLine($"Sum of {t.Count} elements is {t.Sum}.");

یا:

(double Sum, int Count) d = (4.5, 3);


تاپل‌های زبان بر پایهٔ System.ValueTuple هستند؛ یعنی نوع مقدار (value type) و اعضای آن به‌صورت فیلدهای عمومی پیاده‌سازی شده‌اند. نتیجهٔ مستقیم این پیاده‌سازی این است که تاپل‌ها mutable value types هستند، یعنی می‌توان مقادیر فیلدهای‌شان را تغییر داد.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
👍5
شیء (Object) در سی‌شارپ

#csharp_for_beginners

در زبان سی‌شارپ، یک شیء نماینده‌ی یک نمونه (instance) از یک نوع است، که این نوع می‌تواند یک کلاس (class) یا یک ساختار (struct) باشد. یک کلاس یا ساختار مانند نقشه‌ای (blueprint) است که مشخص می‌کند نوع، چه داده‌ها و رفتارهایی دارد، و شیء بخشی از حافظه است که مطابق این نقشه ایجاد و پیکربندی می‌شود. برنامه ممکن است چندین شیء از یک کلاس ایجاد کند.

شیء‌ها همچنین می‌توانند در متغیرها، آرایه‌ها یا مجموعه‌ها ذخیره شوند. کد مشتری (client code) از این متغیرها برای فراخوانی متدها و دسترسی به خصوصیات عمومی شیء استفاده می‌کند.

نمونه‌های ساختار (Struct) و کلاس (Class)

کلاس‌ها
- کلاس‌ها نوع ارجاعی (reference type) هستند.
- متغیر یک شیء کلاس آدرس حافظه آن شیء در heap مدیریت‌شده را نگه می‌دارد.
- اگر یک متغیر کلاس به متغیر دیگر نسبت داده شود، هر دو متغیر به همان شیء اشاره می‌کنند.
- نمونه‌های کلاس معمولاً با عملگر new ایجاد می‌شوند.

مثال:
Person person1 = new Person("Leopold", 6);
Person person2 = person1;
person2.Name = "Molly";
// حالا person1.Name هم "Molly" است، زیرا هر دو به یک شیء اشاره دارند


استراکت‌ها
- استراکت‌ها نوع مقداری (value type) هستند.
- متغیر یک struct، یک کپی کامل از شیء را نگه می‌دارد.
- نمونه‌های struct می‌توانند با new ایجاد شوند، اما الزامی نیست.

مثال:
Person p1 = new Person("Alex", 9);
Person p2 = p1;
p2.Name = "Spencer";
// p1 تغییر نکرده است، زیرا p2 کپی مستقل است


نکات مهم حافظه
- حافظه‌ی کلاس‌ها در managed heap ذخیره می‌شود و توسط garbage collector بازیابی می‌شود.
- حافظه‌ی structها معمولاً در stack ذخیره می‌شود و هنگام خروج از محدوده از بین می‌رود.
- این تفاوت دلیل رفتار متفاوت در کپی و مقایسه بین کلاس و struct است.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
❤3👍1
باکسینگ (Boxing) و آنباکسینگ (Unboxing)

#csharp_for_beginners

باکسینگ (Boxing)

باکسینگ Boxing زمانی اتفاق می‌افتد که یک مقدار از نوع‌های مقداری مثل int یا double به یک نوع مرجع مانند object تبدیل شود. در این فرایند یک شیء جدید در حافظهٔ heap ایجاد می‌شود و مقدار داخل آن قرار می‌گیرد. بعد از انجام باکسینگ Boxing، مقدار اولیه و مقدار قرار داده‌شده داخل شیء دو داده‌ی جداگانه خواهند بود و این عملیات به دلیل ایجاد شیء جدید از نظر عملکردی هزینه‌بر است.

نمونه کد:
int i = 123;
object o = i; // جعبه‌سازی
i = 456;
Console.WriteLine(i);
Console.WriteLine(o);


آنباکسینگ (Unboxing)
اما Unboxing تبدیل برعکس Boxing است و زمانی رخ می‌دهد که بخواهیم مقدار موجود در یک شیء از نوع object را دوباره به نوع مقداری اصلی خود تبدیل کنیم. این کار باید به صورت صریح انجام شود، یعنی لازم است نوع مقصد را حتماً با cast مشخص کنیم. در زمان اجرای برنامه بررسی می‌شود که آیا شیء واقعاً حاصل یک عملیات Boxing از همان نوع مقداری مورد انتظار هست یا خیر. اگر بررسی موفق باشد، مقدار ذخیره ‌شده در heap به یک متغیر مقداری کپی می‌شود. اما اگر شیء تهی (null) باشد یا نوع واقعی آن با نوعی که انتظار داریم مطابقت نداشته باشد، برنامه خطاهایی مانند NullReferenceException یا InvalidCastException تولید می‌کند.

نمونه کد:
int i = 123;
object o = i; // جعبه‌سازی

try
{
int j = (int)o; // ازجعبه‌سازی درست
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}


نمونهٔ خطا:
int i = 123;
object o = i;

try
{
short x = (short)o; // خطای InvalidCastException
}
catch (InvalidCastException e)
{
Console.WriteLine("Incorrect unboxing");
}


باکسینگ Boxing و آنباکسینگ Unboxing به دلیل تخصیص حافظه و بررسی نوع در زمان اجرا از نظر عملکردی هزینه‌بر هستند. در بخش‌هایی از برنامه که این عملیات زیاد انجام می‌شود ممکن است باعث کاهش کارایی شوند. برای جلوگیری از این مشکل، استفاده از Genericها می‌تواند بسیار مؤثر باشد زیرا تبدیل‌های غیرضروری را حذف می‌کند.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
❤4👍1
داینامیک (dynamic)

#csharp_for_beginners

نوع dynamic یک نوع static است اما وقتی متغیری از نوع dynamic باشد کنترل نوع کامپایلر نادیده گرفته می‌شود. یعنی معمولاً مانند نوع object رفتار می‌کند اما کامپایلر فرض می‌کند که هر عملی روی آن امکان‌پذیر است بدون اینکه نوع دقیق آن را بداند.
نتیجه این کار این است که وقتی با dynamic کار می‌کنید لازم نیست بدانید مقدار آن دقیقاً از کجا آمده مثلا از COM API یا یک زبان دینامیک یا از DOM HTML یا بازتاب (reflection).
اگر کد شما نادرست باشد خطا در زمان اجرا ظاهر می‌شود نه زمان کامپایل

مثال:
class ExampleClass
{
public void exampleMethod1(int i) { }
public void exampleMethod2(string str) { }
}

static void Main(string[] args)
{
ExampleClass ec = new ExampleClass()
dynamic dynamic_ec = new ExampleClass()
dynamic_ec.exampleMethod1(10, 4)
dynamic_ec.someMethod("some argument", 7, null)
dynamic_ec.nonexistentMethod()
}


نتیجه عمل روی متغیر dynamic
بیشتر عملیات روی dynamic باز هم نتیجه‌ای از نوع dynamic می‌دهند مثلا

dynamic d = 1
var testSum = d + 3


در اینجا testSum خودش dynamic خواهد بود، اما بعضی از عملیات‌ها نتیجه‌ای غیر dynamic دارند مثل تبدیل به نوع خاص یا ساخت شی با آرگومان‌های dynamic.

var testInstance = new ExampleClass(d)


در اینجا نوع testInstance برابر ExampleClass خواهد بود نه dynamic

کاربردها
داینامیک زمانی مفید است که بخواهید دیر-بایندینگ (late binding) داشته باشید یعنی تصمیم‌گیری نوع و فراخوانی متدها یا پراپرتی‌ها در زمان اجرا انجام شود نه کامپایل.
برای Interop یا COM زمانی که با APIهای COM کار می‌کنید dynamic دیگر لازم نیست هر بار casting انجام دهید.
برای زبان‌های دینامیک یا DOM یا reflection وقتی ساختار داده یا API تان در زمان اجرا معلوم می‌شود dynamic انعطاف بیشتری می‌دهد.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
👍7❤2
دلیگیت (delegate)

#csharp_for_beginners

دلیگیت‌ها (delgate) در زبان سی‌شارپ نوعی داده‌اند که مرجع به یک یا چند متد را نگه می‌دارند. Delegateها شبیه اشاره‌گر تابع هستند اما به‌صورت شیءگرا پیاده‌سازی شده‌اند. این ویژگی باعث می‌شود فقط متدهایی با امضای مشخص بتوانند به یک delegate متصل شوند.

برای تعریف یک delegate از کلمه کلیدی delegate استفاده می‌شود. تعریف delegate مشابه امضای یک متد است و مشخص می‌کند چه نوع متدی می‌تواند به آن نسبت داده شود:

public delegate void Callback(string message);


این delegate می‌تواند به هر متدی متصل شود که یک پارامتر از نوع string دریافت کند و مقدار بازگشتی نداشته باشد.

پس از تعریف delegate، می‌توان یک نمونه از آن ایجاد کرد و یک متد سازگار را به آن نسبت داد.

static void DelegateMethod(string message)
{
Console.WriteLine(message);
}

Callback handler = DelegateMethod;


در این مثال، متد DelegateMethod به delegate متصل شده است. اکنون می‌توان delegate را مانند یک متد فراخوانی کرد.

handler("Hello World");


یکی از کاربردهای مهم delegate استفاده از آن به‌عنوان callback است. در این حالت، delegate به‌عنوان پارامتر به یک متد دیگر ارسال می‌شود.

static void MethodWithCallback(int a, int b, Callback callback)
{
callback("Result: " + (a + b));
}


متد بالا بدون اطلاع از جزئیات متد callback، آن را در زمان مناسب اجرا می‌کند.

Delegateها می‌توانند چندین متد را به‌صورت هم‌زمان نگه دارند. به این نوع delegate، multicast delegate گفته می‌شود.

Callback handler = DelegateMethod;
handler += AnotherMethod;


در این حالت، هنگام فراخوانی delegate، هر دو متد اجرا می‌شوند.

دلیگیت‌ها اشیاء هستند و می‌توان آن‌ها را ذخیره کرد، به متدها ارسال کرد یا در propertyها استفاده کرد. همچنین eventها در C# بر پایه دdelegate ساخته می‌شوند و از همین سازوکار برای اطلاع‌رسانی استفاده می‌کنند.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
👍3❤1
مهاجرت از تایپ‌اسکریپت (۲.۵ میلیون خط کد) به سی‌شارپ

در بلاگ زیر، CTO شرکت Motion توضیح می‌دهد که چرا تصمیم گرفته‌اند کدهای خود را از #typescript به #csharp ببرند...
دلایلی که آورده بسیار قابل توجه هستند و ارزش خواندن و فکر کردن را دارند. ما هم تقریبا به دلایل مشابهی در چند سال گذشته پروژه‌های جاواسکریپتی خود را به سی‌شارپ منتقل کردیم.
حتی در دو پروژه اخیر که با شرکت‌های کانادایی بوده، اولین کار مهاجرت از کدهای #react به #blazor بوده است.

نظر شما چیه؟

🔗 در این صفحه می‌توانید مطلب کامل را بخوانید.

#مهران_داودی (لینکدین - بلاگ)

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
1👍6❤5👎2🔥1🤔1
مفهوم Generics در سی‌شارپ

#csharp_for_beginners

در برنامه‌نویسی، معمولاً کلاس‌ها و متدها برای نوع خاصی از داده طراحی می‌شوند. برای مثال ممکن است یک کلاس فقط برای اعداد صحیح یا فقط برای رشته‌ها نوشته شود. این موضوع باعث افزایش حجم کد و کاهش انعطاف‌پذیری برنامه می‌شود. Generics این مشکل را حل می‌کند و امکان تعریف کلاس‌ها و متدهای عمومی را فراهم می‌سازد.

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

ساختار کلاس Generic
ساختار کلی یک کلاس جنریک به شکل زیر است:

class ClassName<T>
{
T data;

public ClassName(T value)
{
data = value;
}

public void Display()
{
Console.WriteLine(data);
}
}


در این مثال، T می‌تواند هر نوع داده‌ای مانند int، string یا حتی کلاس‌های سفارشی باشد.

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

جنریک (Generic) با چند پارامتر نوع
در سی‌شارپ می‌توان از چند پارامتر نوع نیز استفاده کرد:

class Pair<T1, T2>
{
public T1 First;
public T2 Second;

public Pair(T1 first, T2 second)
{
First = first;
Second = second;
}
}


نمونه استفاده:

Pair<int, string> pair = new Pair<int, string>(1, "One");


در این مثال، T1 برابر int و T2 برابر string خواهد بود.

کاربرد Generics در کتابخانه‌های سی‌شارپ

بسیاری از کلاس‌های آماده در فضای نام System.Collections.Generic بر پایه جنریک‌ها ساخته شده‌اند. برای مثال:

List<T>
Dictionary<TKey, TValue>
Queue<T>
Stack<T>

این کلاس‌ها امکان ذخیره و مدیریت داده‌ها را به صورت ایمن و بهینه فراهم می‌کنند.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
❤5👍4
آشنایی با Dictionary در سی‌شارپ

#csharp_for_beginners

در زبان برنامه‌نویسی سی‌شارپ، ساختار داده‌ی دیکشنری (Dictionary) برای ذخیره‌سازی اطلاعات به صورت «کلید و مقدار» استفاده می‌شود. هر کلید (Key) باید یکتا باشد و به یک مقدار (Value) اشاره کند. این ساختار در فضای نام System.Collections.Generic قرار دارد و به دلیل سرعت بالای جستجو، یکی از پرکاربردترین کالکشن‌ها در سی‌شارپ محسوب می‌شود.

مثال برای ساخت:

csharp

Dictionary<int, string> students = new Dictionary<int, string>();

در مثال بالا، نوع کلید int و نوع مقدار string است.

افزودن داده به Dictionary

برای اضافه کردن داده‌ها معمولاً از متد Add() استفاده می‌شود:
students.Add(1, "Ali");
students.Add(2, "Sara");
students.Add(3, "Reza");


نمایش اطلاعات Dictionary

برای نمایش عناصر از حلقه ها استفاده می‌شود:
foreach (var item in students)
{
Console.WriteLine($"Key: {item.Key}, Value: {item.Value}");
}


خروجی:

Key: 1, Value: Ali
Key: 2, Value: Sara
Key: 3, Value: Reza
Key: 4, Value: Mina


حذف عناصر

برای حذف یک عنصر:
students.Remove(1);


و برای حذف تمام داده‌ها:
students.Clear();


🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
❤3🔥3
لینک (LINQ) در سی‌شارپ

#csharp_for_beginners

لینک (LINQ) یا Language Integrated Query قابلیتی در زبان سی‌شارپ است که امکان جستجو، فیلتر و پردازش داده‌ها را مستقیماً داخل خود زبان فراهم می‌کند.

در گذشته برای کار با منابع داده مختلف مثل SQL، XML یا سرویس‌های وب باید از زبان‌های جداگانه استفاده می‌شد، اما LINQ این مشکل را حل می‌کند و همهٔ عملیات کوئری‌نویسی را به شکلی یکپارچه داخل #C ارائه می‌دهد.

ویژگی‌های اصلی LINQ

▫️امکان نوشتن Query به صورت خوانا و کوتاه

▫️ پشتیبانی از Type Checking در زمان کامپایل

▫️استفاده یکسان برای انواع منابع داده

نمونه‌ای از LINQ :

int[] scores = [97, 92, 81, 60];

IEnumerable<int> scoreQuery =
from score in scores
where score > 80
select score;

foreach (var i in scoreQuery)
{
Console.Write(i + " ");
}


خروجی :

97 92 81

عملگر from منبع داده را مشخص می‌کند
عملگر where فیلتر را انجام می‌دهد
عملگر select دادهٔ نهایی را انتخاب می‌کند

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
👍5❤2
کلاس Static در سی‌شارپ

#csharp_for_beginners

در زبان سی‌شارپ، کلاس Static کلاسی است که با کلیدواژه static تعریف می‌شود. این نوع کلاس فقط می‌تواند شامل اعضای استاتیک (مانند فیلدها، متدها، ویژگی‌ها و رویدادها) باشد و امکان ساختن شیء (Object) از آن وجود ندارد. اعضای آن مستقیماً از طریق نام کلاس فراخوانی می‌شوند.

تعریف کلاس Static:

static class Utility
{
public static void PrintMessage(string msg)
{
Console.WriteLine(msg);
}
}


استفاده:

Utility.PrintMessage("Hello World");


در این مثال، بدون ایجاد شیء از کلاس Utility، متد PrintMessage مستقیماً فراخوانی می‌شود.

ویژگی‌های مهم کلاس Static
▫️با کلمه کلیدی static تعریف می‌شود.
▫️تمام اعضای آن باید استاتیک باشند.
▫️نمی‌توان با new از آن نمونه‌سازی کرد.
▫️به صورت ضمنی sealed است؛ بنابراین قابل ارث‌بری نیست.
▫️نمی‌تواند از کلاس دیگری ارث ببرد.
▫️نمی‌تواند اعضای نمونه‌ای (Instance Members) داشته باشد.

فیلدها و ویژگی‌های Static
کلاس‌های استاتیک می‌توانند داده‌های مشترک در کل برنامه را نگهداری کنند:

static class Config
{
public static string AppName { get; set; } = "MyApp";
public static int Version { get; set; } = 1;
}


استفاده:

Console.WriteLine(Config.AppName);
Console.WriteLine(Config.Version);


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

محدودیت‌های کلاس Static
▫️امکان ایجاد شیء از آن وجود ندارد.
▫️نمی‌تواند اعضای غیراستاتیک داشته باشد.
▫️قابل ارث‌بری نیست.
▫️نمی‌تواند Interfaceها را پیاده‌سازی کند.


کاربردهای کلاس Static
▫️متدهای کمکی (Utility Methods) مانند توابع ریاضی.
▫️تنظیمات سراسری برنامه (Configuration).
▫️ثبت لاگ (Logging).
▫️توابعی که به وضعیت یک شیء وابسته نیستند.

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
👍10
پیاده‌سازی Linked List در سی‌شارپ

#csharp_for_beginners

در این مقاله، ساختار دادهٔ LinkedList در زبان سی‌شارپ معرفی شده است. این ساختار یک لیست پیوندی دوطرفه (Doubly Linked List) است که امکان درج و حذف سریع عناصر را در هر نقطه از لیست فراهم می‌کند. برخلاف آرایه‌ها، عناصر در حافظه به‌صورت پشت‌سرهم ذخیره نمی‌شوند و هر عنصر در قالب یک گره (Node) نگهداری می‌شود.

ساختار LinkedList
هر گره در LinkedList<T> شامل سه بخش است:

مقدار داده (Value)
اشاره‌گر به گره قبلی (Previous)
اشاره‌گر به گره بعدی (Next)

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

ایجاد یک LinkedList

برای استفاده از این ساختار ابتدا باید فضای نام زیر را اضافه کنیم:

using System.Collections.Generic;



سپس لیست را ایجاد می‌کنیم:

LinkedList<int> list = new LinkedList<int>();


افزودن عناصر:


مهم‌ترین متدهای افزودن عنصر عبارت‌اند از:

افزودن در ابتدای لیست: ()AddFirst
افزودن در انتهای لیست: ()AddLast
افزودن قبل از یک گره مشخص: ()AddBefore
افزودن بعد از یک گره مشخص: ()AddAfter


نمونه کد:

LinkedList<int> list = new LinkedList<int>();

list.AddFirst(20);
list.AddLast(30);
list.AddLast(40);

foreach (int item in list)
{
Console.WriteLine(item);
}



خروجی:

20
30
40

برای حذف عناصر نیز متدهای مختلفی وجود دارد:

حذف اولین رخداد یک مقدار: Remove(T value)
حذف اولین گره: RemoveFirst()
حذف آخرین گره: RemoveLast()
حذف یک گره مشخص: Remove(LinkedListNode<T>)
حذف تمام عناصر لیست: Clear()

جستجوی عناصر
متد Contains() بررسی می‌کند که آیا یک مقدار در لیست وجود دارد یا خیر:

LinkedList<int> list = new LinkedList<int>();

list.AddLast(10);
list.AddLast(20);
list.AddLast(30);

Console.WriteLine(list.Contains(20));
Console.WriteLine(list.Contains(100));


خروجی:

True
False

🔗 مطلب کامل را در این لینک می‌توانید مطالعه کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
🔥4❤2👎1
آشنایی با Union Types در سی‌شارپ ۱۵

#csharp_for_beginners

یکی از قابلیت‌های جذابی که قرار است به سی‌شارپ ۱۵ اضافه شود، Union Types است. این ویژگی سال‌هاست در زبان‌هایی مانند TypeScript وجود دارد و به توسعه‌دهندگان اجازه می‌دهد نوعی تعریف کنند که بتواند یکی از چند نوع مشخص را در خود نگه دارد.

فرض کنید می‌خواهیم مجموعه‌ای از حیوانات خانگی را نگهداری کنیم:

List<object> pets =
[
new Dog("Fido"),
new Cat("tabby"),
new Bird { Species = "crow" }
];



در این مثال از List<object> استفاده کرده‌ایم چون اشیاء موجود در لیست از انواع مختلفی هستند.

اما این راهکار یک مشکل اساسی دارد؛ هر نوع شیء دیگری نیز می‌تواند وارد این لیست شود:

pets.Add(new Shark(300));



در حالی که کوسه (Shark) اصلاً جزو حیوانات خانگی موردنظر ما نیست.

برای پردازش این داده‌ها معمولاً از Pattern Matching استفاده می‌کنیم:

var description = pet switch
{
Dog dog => dog.Name,
Cat(var adjective) => $"A {adjective} cat",
Bird { Species: var species } => $"A {species}"
};


اما کامپایلر هیچ اطلاعی ندارد که چه نوع‌هایی مجاز هستند و چه نوع‌هایی نباید در این مجموعه قرار بگیرند.
راه‌حل: Union Types در سی‌شارپ ۱۵ می‌توان یک Union تعریف کرد:

union Pet(Dog, Cat, Bird);


این تعریف به کامپایلر اعلام می‌کند که نوع Pet فقط می‌تواند یکی از این سه نوع باشد:
اکنون می‌توان لیست را به شکل زیر تعریف کرد:
List<Pet> pets =
[
new Dog("Fido"),
new Cat("tabby"),
new Bird { Species = "crow" }
];


در این حالت اگر بخواهیم یک Shark به لیست اضافه کنیم، کامپایلر خطا خواهد داد؛ چون Shark جزو اعضای Union نیست.

یکی از مزیت های مهم Union Types این است که می‌توان مجموعه‌ای مشخص از انواع مرتبط را تحت یک نوع واحد تعریف کرد.

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

برای مثال:

var description = pet switch
{
Dog dog => dog.Name,
Cat(var adjective) => $"A {adjective} cat",
Bird { Species: var species } => $"A {species}"
};

اگر یکی از انواع تعریف‌شده در Union را فراموش کنیم، کامپایلر هشدار نمایش خواهد داد.

این موضوع باعث می‌شود بسیاری از خطاها قبل از اجرای برنامه شناسایی شوند.

علاوه بر مشخص کردن انواع مجاز، می‌توان رفتارها و قابلیت‌های مشترک را نیز مستقیماً درون خود Union پیاده‌سازی کرد.

برای مثال:

union Pet(Dog, Cat, Bird)
{
public string Description => this switch
{
Dog dog => dog.Name,
Cat(var adjective) => $"A {adjective} cat",
Bird { Species: var species } => $"A {species}"
};
}



در این مثال ویژگی Description مستقیماً داخل Union تعریف شده است.

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

این ویژگی باعث می‌شود کدها تمیزتر و نگهداری آن‌ها ساده‌تر شود.

تعریف Union با Attributeعلاوه بر سینتکس اختصاصی Union، روش دیگری نیز برای تعریف Unionها در نظر گرفته شده است که مبتنی بر Attribute است.

برای مثال:

[Union]
struct Result<T>
{
}


چرا Attribute-Based Union اهمیت دارد؟
این روش دو مزیت مهم دارد.

۱. بهبود کارایی (Performance)

بدون استفاده از union ها در برخی شرایط باعث Boxing می‌شود.

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

برای مثال اگر Union شما از چند Struct کوچک تشکیل شده باشد، جلوگیری از Boxing می‌تواند تأثیر قابل توجهی روی عملکرد برنامه داشته باشد.

۲. ساخت Unionهای کاستوم با کمترین زحمت قبل از معرفی Union Types، بسیاری از توسعه‌دهندگان تلاش می‌کردند با استفاده از کلاس‌های پایه، اینترفیس‌ها یا حتی قراردادهای مستندسازی و کامنت‌ها، ساختاری شبیه Union ایجاد کنند.

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

🔗 ویدئو را در این لینک می‌توانید می‌توانید مشاهده کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
❤6👍6
دی‌کانستراکشن تاپل (Tuple Deconstruction) در سی‌شارپ

#csharp_for_beginners

قابلیت دی‌کانستراکشن تاپل (Tuple Deconstruction) از نسخه سی‌شارپ ۷.۰ به زبان سی‌شارپ اضافه شد. این قابلیت به شما اجازه می‌دهد اعضای یک Tuple را به‌طور هم‌زمان در چند متغیر مستقل قرار دهید. به این ترتیب دیگر نیازی نیست برای دسترسی به هر عضو از Item1، Item2 یا نام اعضای Tuple استفاده کنید و می‌توانید تمام مقادیر را تنها با یک دستور استخراج کنید.

به عنوان مثال، فرض کنید متد یک Tuple شامل اطلاعات یک حیوان خانگی را برمی‌گرداند:

(string Type, string Name, int Height, int Age, string Color) GetPet()
{
return ("Dog", "Max", 60, 4, "Brown");
}



می‌توان تمام مقادیر بازگشتی را به‌صورت هم‌زمان دریافت کرد:

(string type, string name, int height, int age, string color) = GetPet();



در این مثال، هر عضو Tuple مستقیماً در متغیر متناظر خود قرار می‌گیرد.

تعیین صریح نوع متغیرها
در این روش، نوع هر متغیر به‌صورت صریح داخل پرانتز نوشته می‌شود.

(string type, string name, int height, int age, string color) = GetPet();


مقدار اول در type
مقدار دوم در name
مقدار سوم در height
مقدار چهارم در age
مقدار پنجم در color

نادیده گرفتن اعضای غیرضروری با Discard

اگر به همه اعضای Tuple نیاز نداشته باشید، می‌توانید از Discard که با علامت _ نمایش داده می‌شود استفاده کنید.

(string type, _, int height, _, string color) = GetPet();



مقدار اول در type ذخیره می‌شود.
مقدار دوم نادیده گرفته می‌شود.
مقدار سوم در height قرار می‌گیرد.
مقدار چهارم نادیده گرفته می‌شود.
مقدار پنجم در color ذخیره می‌شود.

استفاده از _ باعث می‌شود مقدار مربوطه دریافت شود، اما در هیچ متغیری ذخیره نشود.

قوانین و محدودیت‌های دی‌کانستراکشن تاپل

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

- تعداد متغیرها باید با تعداد اعضای Tuple برابر باشد.

- اگر Tuple پنج عضو داشته باشد، باید در سمت چپ نیز پنج متغیر یا Discard (_) وجود داشته باشد.

نمونه صحیح:

(var type, var name, var height, var age, var color) = GetPet();


🔗 ویدئو را در این لینک می‌توانید می‌توانید مشاهده کنید.

⁉️ برای بحث و تبادل نظر فنی در مورد این پست، نظرات خود را با ما در قسمت کامنت‌ها به اشتراک بگذارید.

کانال تلگرام:
@SoftwarePhilosophy

______
👍1