آموزش C# از صفر تا صد: راهنمای کامل برای مبتدیان

فهرست مطالب

آموزش C# از صفر تا صد: راهنمای کامل برای مبتدیان

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

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

مقدمه: چرا C# را انتخاب کنیم؟

C# یک زبان برنامه‌نویسی مدرن، شیءگرا و تایپ‌شده (Type-safe) است که توسط مایکروسافت به عنوان بخشی از پلتفرم .NET توسعه یافته است. این زبان که شباهت‌های زیادی به جاوا و ++C دارد، به گونه‌ای طراحی شده که توسعه‌دهندگان بتوانند برنامه‌های قوی، مقیاس‌پذیر و امن را به سرعت ایجاد کنند.

تاریخچه و تکامل C#

سی‌شارپ اولین بار در سال ۲۰۰۰ توسط آندرس هلزبرگ (Anders Hejlsberg)، خالق دلفی و Turbo Pascal، معرفی شد. هدف اصلی از ایجاد C#، ارائه یک زبان برنامه‌نویسی کارآمد برای پلتفرم .NET بود که از قابلیت‌های برنامه‌نویسی شیءگرا به طور کامل پشتیبانی کند. از آن زمان تاکنون، C# به طور مداوم تکامل یافته و با هر نسخه جدید، قابلیت‌ها و ویژگی‌های قدرتمندتری به آن اضافه شده است. با معرفی .NET Core و سپس .NET 5/6/7/8، C# به یک زبان کراس‌پلتفرم (قابل اجرا بر روی ویندوز، لینوکس و macOS) تبدیل شده و افق‌های جدیدی را برای توسعه‌دهندگان گشوده است.

چرا یادگیری C# یک سرمایه‌گذاری هوشمندانه است؟

  1. تنوع کاربرد (Versatility): C# یکی از همه‌کاره‌ترین زبان‌های برنامه‌نویسی موجود است. با C# و اکوسیستم .NET می‌توانید برنامه‌های زیر را توسعه دهید:
    • برنامه‌های دسکتاپ: با استفاده از WPF (Windows Presentation Foundation) یا WinForms، می‌توانید اپلیکیشن‌های قدرتمند و زیبا برای ویندوز بسازید.
    • برنامه‌های وب: ASP.NET Core، فریم‌ورک وب مایکروسافت، امکان توسعه وب‌سایت‌ها، وب‌سرویس‌ها و API‌های RESTful را فراهم می‌کند. Blazor نیز به شما اجازه می‌دهد که رابط کاربری وب را با C# بسازید.
    • بازی‌سازی: موتور بازی‌سازی محبوب Unity از C# به عنوان زبان اصلی اسکریپت‌نویسی استفاده می‌کند. بسیاری از بازی‌های پرطرفدار جهان با Unity و C# ساخته شده‌اند.
    • اپلیکیشن‌های موبایل: با Xamarin و اخیراً .NET MAUI (Multi-platform App UI)، می‌توانید اپلیکیشن‌های بومی (Native) برای iOS، Android، macOS و Windows را با یک کدبیس واحد C# توسعه دهید.
    • خدمات ابری (Cloud Services): C# در پلتفرم‌های ابری مانند Azure (مایکروسافت)، AWS (آمازون) و Google Cloud برای توسعه توابع بدون سرور (Serverless Functions)، میکروسرویس‌ها و سایر سرویس‌های ابری به کار می‌رود.
    • هوش مصنوعی و یادگیری ماشین: با ML.NET، می‌توانید مدل‌های یادگیری ماشین را در برنامه‌های C# خود ادغام کنید.
    • اینترنت اشیاء (IoT): C# برای برنامه‌نویسی دستگاه‌های IoT نیز کاربرد دارد.
  2. بازار کار پررونق: تقاضا برای توسعه‌دهندگان C#/.NET در سراسر جهان و به خصوص در ایران بسیار بالاست. شرکت‌های بزرگ و کوچک به دنبال استخدام متخصصان C# برای پروژه‌های متنوع خود هستند.
  3. پشتیبانی قوی از مایکروسافت: C# تحت حمایت مایکروسافت است، که به معنای به‌روزرسانی‌های منظم، ابزارهای توسعه پیشرفته (مانند Visual Studio) و مستندات جامع است.
  4. جامعه کاربری فعال: C# دارای یک جامعه بزرگ و فعال از توسعه‌دهندگان است. این بدان معناست که منابع آموزشی فراوان، انجمن‌های پشتیبانی و کتابخانه‌های متن‌باز زیادی برای کمک به شما در دسترس هستند.
  5. زبان قدرتمند و ایمن: C# یک زبان تایپ‌شده است که به شناسایی خطاهای برنامه‌نویسی در زمان کامپایل کمک می‌کند. همچنین، ویژگی‌هایی مانند جمع‌آوری زباله (Garbage Collection) مدیریت حافظه را آسان‌تر کرده و از نشت حافظه جلوگیری می‌کند.
  6. ابزارهای توسعه عالی: Visual Studio، IDE (محیط توسعه یکپارچه) اصلی برای C#، یکی از بهترین و قدرتمندترین ابزارهای توسعه نرم‌افزار در جهان است که با امکاناتی مانند IntelliSense، دیباگر پیشرفته و ابزارهای Refactoring، بهره‌وری توسعه‌دهنده را به شدت افزایش می‌دهد.

با توجه به این دلایل، C# نه تنها یک زبان برنامه‌نویسی برای شروع است، بلکه مسیری برای تخصص در حوزه‌های مختلف و ساختن نرم‌افزارهای پیچیده و کاربردی را برای شما هموار می‌کند.

آماده‌سازی محیط توسعه: گام به گام تا اولین برنامه

قبل از اینکه شروع به کدنویسی در C# کنیم، نیاز داریم محیط توسعه مناسب را روی سیستم خود نصب و پیکربندی کنیم. قدرتمندترین ابزار برای توسعه با C#، محیط Visual Studio است که توسط مایکروسافت ارائه شده است.

نصب Visual Studio Community Edition

Visual Studio Community Edition یک نسخه رایگان از Visual Studio است که برای دانشجویان، پروژه‌های متن‌باز و تیم‌های کوچک (تا ۵ توسعه‌دهنده) مناسب است و تمام امکانات لازم برای شروع یادگیری C# را در اختیار شما قرار می‌دهد.

  1. دانلود Visual Studio Installer: به وب‌سایت رسمی Visual Studio بروید و نسخه Community را دانلود کنید.
  2. اجرای Installer: فایل دانلود شده را اجرا کنید. این فایل، ابزار Visual Studio Installer را راه‌اندازی می‌کند.
  3. انتخاب Workloads: در Visual Studio Installer، از شما خواسته می‌شود Workload (بار کاری) مورد نیاز خود را انتخاب کنید. برای شروع آموزش C#، حداقل Workload‌های زیر را انتخاب کنید:
    • .NET Desktop Development: برای توسعه برنامه‌های دسکتاپ Windows Forms و WPF.
    • ASP.NET and web development: برای توسعه وب‌سایت‌ها و وب‌سرویس‌ها با ASP.NET Core.
    • .NET Cross-platform Development: این گزینه شامل SDKهای .NET Core برای توسعه کراس‌پلتفرم می‌شود.

    می‌توانید Workload‌های دیگری مانند “Game development with Unity” یا “Mobile development with .NET MAUI” را نیز در صورت تمایل نصب کنید، اما برای شروع ضروری نیستند.

  4. نصب: پس از انتخاب Workload‌ها، روی دکمه “Install” کلیک کنید. این فرآیند ممکن است بسته به سرعت اینترنت و قدرت سیستم شما زمان‌بر باشد.
  5. ورود به حساب مایکروسافت: پس از نصب، Visual Studio از شما می‌خواهد که با حساب مایکروسافت خود (مانند Outlook، Hotmail یا Live) وارد شوید. این کار برای فعال‌سازی نسخه Community الزامی است.

اولین برنامه C#: “Hello, World!”

حالا که Visual Studio نصب شده است، بیایید اولین برنامه C# خود را بنویسیم: یک برنامه ساده که عبارت “Hello, World!” را روی کنسول نمایش می‌دهد.

  1. ایجاد پروژه جدید:
    • Visual Studio را باز کنید.
    • در صفحه شروع، روی “Create a new project” کلیک کنید.
    • در قسمت جستجو، “Console App” را جستجو کنید.
    • قالب “Console App” (که برای C# و .NET است) را انتخاب کرده و روی “Next” کلیک کنید.
    • نام پروژه را “HelloWorldApp” یا هر نام دلخواه دیگری بگذارید و مکان ذخیره‌سازی آن را انتخاب کنید. سپس روی “Next” کلیک کنید.
    • نسخه .NET Framework یا .NET (مثلاً .NET 8.0 یا جدیدترین نسخه موجود) را انتخاب کرده و روی “Create” کلیک کنید.
  2. بررسی ساختار پروژه:

    Visual Studio یک پروژه Console App با ساختار پیش‌فرض ایجاد می‌کند. در Solution Explorer (معمولاً در سمت راست)، فایل `Program.cs` را مشاهده خواهید کرد. این فایلی است که کد اصلی برنامه شما در آن قرار می‌گیرد.

    محتوای پیش‌فرض فایل `Program.cs` ممکن است به شکل زیر باشد:

    Console.WriteLine("Hello, World!");
    

    در نسخه‌های قدیمی‌تر .NET و C#، ساختار کامل‌تری وجود داشت که شامل `using` statement‌ها، `namespace`، `class Program` و متد `Main` بود. اگر نسخه قدیمی‌تر را انتخاب کنید، کدی شبیه به این خواهید دید:

    using System;
    
    namespace HelloWorldApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello, World!");
            }
        }
    }
    

    در هر دو حالت، عبارت `Console.WriteLine(“Hello, World!”);` دستور اصلی است که متن را روی کنسول چاپ می‌کند.

  3. اجرای برنامه:

    برای اجرای برنامه، روی دکمه سبز رنگ “Start” در بالای Visual Studio (یا کلید F5) کلیک کنید. یک پنجره کنسول باز شده و عبارت “Hello, World!” را نمایش می‌دهد، سپس بسته می‌شود (یا اگر در نسخه جدید .NET باشید، تا زمانی که کلید Enter را فشار ندهید، باز می‌ماند).

    تبریک می‌گوییم! شما اولین برنامه C# خود را اجرا کردید.

مفاهیم پایه در ساختار کد C#

  • `using System;` (در پروژه‌های قدیمی‌تر): این خط به کامپایلر می‌گوید که کلاس‌های موجود در فضای نام `System` را در دسترس قرار دهد. `Console` کلاسی است که در فضای نام `System` قرار دارد.
  • `namespace HelloWorldApp` (در پروژه‌های قدیمی‌تر): فضای نام (Namespace) یک روش برای سازماندهی کد است و به جلوگیری از تداخل نام‌ها کمک می‌کند. تمام کلاس‌های شما باید درون یک فضای نام قرار گیرند.
  • `class Program` (در پروژه‌های قدیمی‌تر): C# یک زبان شیءگرا است و تمام کدها باید درون کلاس‌ها قرار گیرند. `Program` نام کلاسی است که برنامه ما را شامل می‌شود.
  • `static void Main(string[] args)` (در پروژه‌های قدیمی‌تر): این متد (تابع) نقطه ورود (Entry Point) هر برنامه C# است. هر زمان که برنامه شما اجرا می‌شود، ابتدا این متد فراخوانی می‌شود.
    • `static`: به این معنی است که متد `Main` متعلق به کلاس `Program` است، نه به یک شیء خاص از آن.
    • `void`: نشان می‌دهد که این متد هیچ مقداری را برنمی‌گرداند.
    • `Main`: نام استاندارد متد اصلی.
    • `string[] args`: آرایه‌ای از رشته‌ها است که می‌تواند برای دریافت آرگومان‌های خط فرمان در زمان اجرای برنامه استفاده شود.
  • `Console.WriteLine(“Hello, World!”);`:**
    • `Console`: یک کلاس است که توابع مربوط به ورودی/خروجی کنسول را فراهم می‌کند.
    • `WriteLine`: یک متد از کلاس `Console` است که متن را روی کنسول چاپ کرده و سپس به خط بعدی می‌رود.
    • `”Hello, World!”`: یک رشته (String Literal) است که قرار است چاپ شود.
    • `;`: نقطه ویرگول، نشان‌دهنده پایان یک دستور در C# است.

درک این مفاهیم اولیه برای شروع یادگیری C# حیاتی است. در بخش‌های بعدی به تفصیل در مورد هر یک از این مفاهیم صحبت خواهیم کرد.

مفاهیم بنیادی C#: بلوک‌های سازنده هر برنامه

پس از آماده‌سازی محیط توسعه، نوبت به آشنایی با اساسی‌ترین مفاهیم در C# می‌رسد. این مفاهیم، بلوک‌های سازنده هر برنامه C# هستند.

۱. متغیرها و انواع داده (Variables and Data Types)

متغیرها مکان‌هایی در حافظه کامپیوتر هستند که برای ذخیره داده‌ها استفاده می‌شوند. هر متغیر باید دارای یک نوع داده (Data Type) باشد که نوع اطلاعاتی که می‌تواند ذخیره کند (مانند عدد، متن، یا مقادیر منطقی) را مشخص می‌کند.

انواع داده اصلی (Primitive Data Types):

C# دارای انواع داده داخلی متعددی است که به دو دسته اصلی تقسیم می‌شوند: Value Types و Reference Types.

Value Types (انواع مقداری):
داده‌های این نوع مستقیماً در محلی که متغیر اعلان شده است (معمولاً روی Stack حافظه) ذخیره می‌شوند. هرگاه یک متغیر Value Type را به متغیر دیگری اختصاص دهید، یک کپی از مقدار آن ساخته می‌شود.

  • `int`: اعداد صحیح (مثبت و منفی) با محدوده تقریبی -2 میلیارد تا +2 میلیارد. (۳۲ بیت)
  • `long`: اعداد صحیح بسیار بزرگتر. (۶۴ بیت)
  • `float`: اعداد اعشاری با دقت تک (Single-precision floating-point). (۳۲ بیت)
  • `double`: اعداد اعشاری با دقت دو (Double-precision floating-point)، رایج‌ترین نوع برای اعداد اعشاری. (۶۴ بیت)
  • `decimal`: برای محاسبات دقیق پولی و مالی (دقت بالاتر از float و double).
  • `bool`: مقادیر منطقی `true` (درست) یا `false` (غلط).
  • `char`: یک کاراکتر (مانند ‘A’, ‘b’, ‘1’).

Reference Types (انواع مرجعی):
داده‌های این نوع در Heap حافظه ذخیره می‌شوند و متغیر فقط یک ارجاع (آدرس) به محل ذخیره‌سازی داده را نگهداری می‌کند. هنگامی که یک متغیر Reference Type را به متغیر دیگری اختصاص می‌دهید، فقط آدرس حافظه کپی می‌شود، نه خود داده.

  • `string`: برای ذخیره دنباله‌ای از کاراکترها (متن). رشته‌ها در C# تغییرناپذیر (Immutable) هستند، به این معنی که پس از ایجاد نمی‌توانند تغییر کنند. هر تغییری در یک رشته منجر به ایجاد یک رشته جدید می‌شود.
  • `object`: نوع پایه برای تمام انواع داده‌ها در C#.
  • آرایه‌ها (Arrays)، کلاس‌ها (Classes) و اینترفیس‌ها (Interfaces) نیز از انواع مرجعی هستند.

اعلان و مقداردهی اولیه متغیرها:

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

// اعلان یک متغیر از نوع int
int age; 

// مقداردهی اولیه
age = 30; 

// اعلان و مقداردهی همزمان
string name = "علی"; 
double price = 19.99;
bool isActive = true;
char initial = 'A';

// استفاده از کلمه کلیدی var برای تشخیص نوع داده (Type Inference)
// C# به طور خودکار نوع داده را بر اساس مقداری که به آن اختصاص می دهید، تشخیص می دهد.
var count = 100; // count از نوع int خواهد بود
var message = "سلام دنیا!"; // message از نوع string خواهد بود
var isComplete = false; // isComplete از نوع bool خواهد بود

تبدیل نوع (Type Conversion):

گاهی اوقات نیاز دارید مقدار یک متغیر را از یک نوع به نوع دیگر تبدیل کنید.

  • تبدیل ضمنی (Implicit Conversion): زمانی اتفاق می‌افتد که تبدیل بدون از دست دادن اطلاعات ممکن باشد (مثلاً از `int` به `long` یا از `int` به `double`).
    int myInt = 10;
    double myDouble = myInt; // تبدیل ضمنی از int به double
    long myLong = myInt; // تبدیل ضمنی از int به long
    
  • تبدیل صریح (Explicit Conversion یا Casting): زمانی که ممکن است اطلاعات از دست برود (مثلاً از `double` به `int` یا از `long` به `int`). در این حالت باید از عملگر Cast استفاده کنید.
    double myDouble = 9.78;
    int myInt = (int)myDouble; // تبدیل صریح: myInt برابر با 9 خواهد شد (قسمت اعشاری از بین می رود)
    
    long bigNumber = 2147483648L; // بزرگتر از max value یک int
    int smallNumber = (int)bigNumber; // ممکن است منجر به از دست رفتن اطلاعات شود
    
  • استفاده از کلاس `Convert` یا متدهای `Parse`/`TryParse`:

    برای تبدیل بین انواع داده‌های مختلف، به خصوص از رشته به انواع عددی، می‌توانید از متدهای کلاس `Convert` یا متدهای `Parse` و `TryParse` استفاده کنید.

    string strNumber = "123";
    int num1 = Convert.ToInt32(strNumber); // تبدیل رشته به عدد صحیح
    
    string strDecimal = "45.67";
    double num2 = Convert.ToDouble(strDecimal); // تبدیل رشته به عدد اعشاری
    
    string strBool = "true";
    bool b = Convert.ToBoolean(strBool); // تبدیل رشته به بولین
    
    // Parse: اگر تبدیل ناموفق باشد، خطا (Exception) پرتاب می کند.
    int num3 = int.Parse("789"); 
    
    // TryParse: اگر تبدیل ناموفق باشد، خطا پرتاب نمی کند و false برمی گرداند.
    string invalidNum = "abc";
    int parsedNum;
    bool success = int.TryParse(invalidNum, out parsedNum); 
    // success برابر با false و parsedNum برابر با 0 خواهد بود.
    

۲. عملگرها (Operators)

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

  • عملگرهای محاسباتی (Arithmetic Operators):
    • `+` (جمع)
    • `-` (تفریق)
    • `*` (ضرب)
    • `/` (تقسیم)
    • `%` (باقیمانده تقسیم)
    • `++` (افزایش ۱ واحدی)
    • `–` (کاهش ۱ واحدی)
    • int a = 10, b = 3;
      Console.WriteLine(a + b); // 13
      Console.WriteLine(a - b); // 7
      Console.WriteLine(a * b); // 30
      Console.WriteLine(a / b); // 3 (تقسیم صحیح)
      Console.WriteLine(a % b); // 1
      a++; // a = 11
      b--; // b = 2
      
  • عملگرهای مقایسه‌ای (Relational Operators):
    • `==` (برابر است با)
    • `!=` (نابرابر است با)
    • `>` (بزرگتر از)
    • `<` (کوچکتر از)
    • `>=` (بزرگتر یا مساوی)
    • `<=` (کوچکتر یا مساوی)
    • این عملگرها نتایج `true` یا `false` برمی‌گردانند.

      int x = 5, y = 10;
      Console.WriteLine(x == y); // False
      Console.WriteLine(x != y); // True
      Console.WriteLine(x < y);  // True
      
  • عملگرهای منطقی (Logical Operators):
    • `&&` (AND منطقی): اگر هر دو شرط `true` باشند، نتیجه `true` است.
    • `||` (OR منطقی): اگر حداقل یکی از شرط‌ها `true` باشد، نتیجه `true` است.
    • `!` (NOT منطقی): نتیجه را معکوس می‌کند (`true` را `false` و بالعکس).
    • bool isSunny = true;
      bool isWarm = false;
      Console.WriteLine(isSunny && isWarm); // False
      Console.WriteLine(isSunny || isWarm); // True
      Console.WriteLine(!isSunny);          // False
      
  • عملگرهای تخصیص (Assignment Operators):
    • `=` (تخصیص)
    • `+=`, `-=`, `*=`, `/=`, `%=` (تخصیص ترکیبی)
    • int num = 10;
      num += 5; // معادل num = num + 5; (num = 15)
      num *= 2; // معادل num = num * 2; (num = 30)
      
  • عملگر سه‌تایی (Ternary Operator):

    یک عملگر شرطی مختصر است و مقداری را بر اساس یک شرط برمی‌گرداند. سینتکس آن به شکل `condition ? expression_if_true : expression_if_false` است.

    int score = 75;
    string result = (score >= 60) ? "قبول" : "مردود";
    Console.WriteLine(result); // قبول
    

۳. دستورات کنترل جریان (Control Flow Statements)

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

دستورات شرطی (Conditional Statements):

  • `if`, `else if`, `else`: برای اجرای بلاک‌های کد بر اساس یک یا چند شرط.
    int hour = 14;
    if (hour < 12)
    {
        Console.WriteLine("صبح بخیر!");
    }
    else if (hour < 18)
    {
        Console.WriteLine("بعدازظهر بخیر!");
    }
    else
    {
        Console.WriteLine("شب بخیر!");
    }
    
  • `switch`: برای انتخاب یک بلاک کد از بین چندین گزینه، بر اساس مقدار یک متغیر.
    char grade = 'B';
    switch (grade)
    {
        case 'A':
            Console.WriteLine("عالی!");
            break;
        case 'B':
            Console.WriteLine("خوب!");
            break;
        case 'C':
            Console.WriteLine("متوسط!");
            break;
        default:
            Console.WriteLine("باید بیشتر تلاش کنید.");
            break;
    }
    

حلقه‌ها (Loops):

برای اجرای مکرر یک بلاک کد تا زمانی که یک شرط خاص برآورده شود یا برای هر عنصر در یک مجموعه.

  • `for` Loop: برای تکرار یک بلاک کد تعداد مشخصی از دفعات.
    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine("تکرار شماره: " + i);
    }
    // خروجی:
    // تکرار شماره: 0
    // تکرار شماره: 1
    // تکرار شماره: 2
    // تکرار شماره: 3
    // تکرار شماره: 4
    
  • `while` Loop: برای تکرار یک بلاک کد تا زمانی که یک شرط `true` باشد. شرط قبل از هر تکرار بررسی می‌شود.
    int count = 0;
    while (count < 3)
    {
        Console.WriteLine("Count: " + count);
        count++;
    }
    // خروجی:
    // Count: 0
    // Count: 1
    // Count: 2
    
  • `do-while` Loop: مشابه `while` Loop، با این تفاوت که بلاک کد حداقل یک بار اجرا می‌شود، زیرا شرط پس از اولین تکرار بررسی می‌شود.
    int i = 0;
    do
    {
        Console.WriteLine("Iteration: " + i);
        i++;
    } while (i < 0); // این حلقه فقط یک بار اجرا می شود (زیرا i=0، شرط false است)
    // خروجی:
    // Iteration: 0
    
  • `foreach` Loop: برای پیمایش (Iterating) در عناصر یک مجموعه (مانند آرایه‌ها یا لیست‌ها).
    string[] names = { "علی", "رضا", "مریم" };
    foreach (string name in names)
    {
        Console.WriteLine("نام: " + name);
    }
    // خروجی:
    // نام: علی
    // نام: رضا
    // نام: مریم
    
  • دستورات `break` و `continue`:
    • `break`: برای خروج فوری از حلقه (یا دستور `switch`).
    • `continue`: برای پرش از بقیه کد در تکرار فعلی حلقه و رفتن به تکرار بعدی.
    for (int j = 0; j < 10; j++)
    {
        if (j == 3)
            continue; // اگر j برابر 3 باشد، بقیه کد این تکرار اجرا نمی شود و به تکرار بعدی می رود
        if (j == 7)
            break; // اگر j برابر 7 باشد، حلقه کاملاً متوقف می شود
        Console.WriteLine("J: " + j);
    }
    // خروجی:
    // J: 0
    // J: 1
    // J: 2
    // J: 4
    // J: 5
    // J: 6
    

۴. آرایه‌ها (Arrays)

آرایه مجموعه‌ای از عناصر هم‌نوع است که در خانه‌های حافظه متوالی ذخیره می‌شوند. عناصر آرایه با استفاده از یک اندیس (Index) عددی (که از 0 شروع می‌شود) قابل دسترسی هستند.

اعلان و مقداردهی اولیه آرایه:

// اعلان یک آرایه از 5 عدد صحیح
int[] numbers = new int[5]; 

// مقداردهی به عناصر آرایه
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;

// دسترسی به عناصر آرایه
Console.WriteLine(numbers[0]); // 10
Console.WriteLine(numbers[4]); // 50

// اعلان و مقداردهی اولیه همزمان
string[] fruits = { "سیب", "پرتقال", "موز" };
Console.WriteLine(fruits.Length); // 3 (تعداد عناصر آرایه)

// پیمایش آرایه با حلقه for
for (int i = 0; i < fruits.Length; i++)
{
    Console.WriteLine(fruits[i]);
}

// پیمایش آرایه با حلقه foreach
foreach (string fruit in fruits)
{
    Console.WriteLine(fruit);
}

آرایه‌های چند بعدی (Multi-dimensional Arrays):

می‌توانید آرایه‌های دو بعدی (ماتریس)، سه بعدی و ... ایجاد کنید.

  • آرایه مستطیلی (Rectangular Array): دارای ابعاد ثابت در هر ردیف.
    int[,] matrix = new int[2, 3]; // آرایه 2 ردیف و 3 ستون
    matrix[0, 0] = 1;
    matrix[0, 1] = 2;
    matrix[1, 2] = 6;
    
    // مقداردهی اولیه همزمان
    int[,] anotherMatrix = { {1, 2, 3}, {4, 5, 6} };
    Console.WriteLine(anotherMatrix[1, 1]); // 5
    
  • آرایه دندانه‌دار (Jagged Array): آرایه‌ای از آرایه‌ها که هر ردیف می‌تواند طول متفاوتی داشته باشد.
    int[][] jaggedArray = new int[3][]; // 3 ردیف
    jaggedArray[0] = new int[] { 1, 2, 3 };
    jaggedArray[1] = new int[] { 4, 5 };
    jaggedArray[2] = new int[] { 6, 7, 8, 9 };
    
    Console.WriteLine(jaggedArray[0][2]); // 3
    Console.WriteLine(jaggedArray[1].Length); // 2
    

۵. متدها/توابع (Methods/Functions)

متدها بلاک‌های کدی هستند که یک وظیفه خاص را انجام می‌دهند. استفاده از متدها به ما کمک می‌کند کد را ماژولار، قابل استفاده مجدد و خوانا نگه داریم.

تعریف و فراخوانی متد:

class Calculator
{
    // متدی که دو عدد را جمع کرده و حاصل را برمی گرداند
    public int Add(int num1, int num2)
    {
        int sum = num1 + num2;
        return sum; // بازگرداندن مقدار
    }

    // متدی که مقداری را برنمی گرداند (void) و فقط یک کار را انجام می دهد
    public void DisplayMessage(string message)
    {
        Console.WriteLine(message);
    }

    // متد Main که نقطه ورود برنامه است
    static void Main(string[] args)
    {
        Calculator calc = new Calculator(); // ایجاد یک شیء از کلاس Calculator
        
        int result = calc.Add(10, 5); // فراخوانی متد Add
        Console.WriteLine("نتیجه جمع: " + result); // 15

        calc.DisplayMessage("این یک پیام از متد است."); // فراخوانی متد DisplayMessage
    }
}

پارامترها و آرگومان‌ها (Parameters and Arguments):

  • پارامترها: متغیرهایی که در تعریف متد داخل پرانتز می‌آیند.
  • آرگومان‌ها: مقادیری که هنگام فراخوانی متد به پارامترها ارسال می‌شوند.

ارسال پارامتر (Parameter Passing):

  • ارسال با مقدار (Pass by Value): یک کپی از مقدار آرگومان به پارامتر ارسال می‌شود. تغییر پارامتر درون متد، روی آرگومان اصلی تأثیری ندارد (برای انواع مقداری).
    void ChangeValue(int x)
    {
        x = 100; // این تغییر فقط روی کپی x تاثیر می گذارد
    }
    int original = 10;
    ChangeValue(original);
    Console.WriteLine(original); // 10
    
  • ارسال با ارجاع (Pass by Reference) با `ref`: کلمه کلیدی `ref` باعث می‌شود که خود متغیر به متد ارسال شود، نه کپی آن. تغییرات درون متد روی متغیر اصلی تأثیر می‌گذارد. متغیر باید قبل از ارسال به متد `ref` مقداردهی اولیه شده باشد.
    void ModifyRef(ref int x)
    {
        x = 200;
    }
    int original = 10;
    ModifyRef(ref original);
    Console.WriteLine(original); // 200
    
  • پارامترهای `out`: مشابه `ref` هستند، اما متغیر ارسالی نیازی به مقداردهی اولیه قبل از ارسال ندارد. متد فراخوانی شده باید حتماً به پارامتر `out` مقداری را اختصاص دهد.
    void GetValue(out int x)
    {
        x = 300; // باید در اینجا به x مقدار دهیم
    }
    int result; // نیازی به مقداردهی اولیه نیست
    GetValue(out result);
    Console.WriteLine(result); // 300
    
  • پارامترهای `params`: به شما امکان می‌دهد تعداد متغیری از آرگومان‌ها را به عنوان یک آرایه به متد ارسال کنید.
    public int SumNumbers(params int[] numbers)
    {
        int total = 0;
        foreach (int num in numbers)
        {
            total += num;
        }
        return total;
    }
    // فراخوانی:
    Console.WriteLine(SumNumbers(1, 2, 3));        // 6
    Console.WriteLine(SumNumbers(10, 20, 30, 40)); // 100
    

متد Overloading (سربارگذاری متد):

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

class Greeter
{
    public void SayHello()
    {
        Console.WriteLine("Hello!");
    }

    public void SayHello(string name)
    {
        Console.WriteLine("Hello, " + name + "!");
    }

    public void SayHello(string name, int times)
    {
        for (int i = 0; i < times; i++)
        {
            Console.WriteLine("Hello, " + name + "!");
        }
    }
}

// استفاده:
Greeter greeter = new Greeter();
greeter.SayHello();            // Hello!
greeter.SayHello("زهرا");     // Hello, زهرا!
greeter.SayHello("احمد", 2); // Hello, احمد! (دو بار)

با یادگیری این مفاهیم بنیادی، شما مجهز به ابزارهای لازم برای ساختن منطق برنامه‌های پیچیده‌تر هستید. در بخش بعدی، به قلب C#، یعنی برنامه‌نویسی شیءگرا، خواهیم پرداخت.

برنامه‌نویسی شیءگرا (OOP) در C#: ستون فقرات توسعه نرم‌افزار

C# یک زبان برنامه‌نویسی کاملاً شیءگرا (Object-Oriented Programming - OOP) است. OOP یک پارادایم برنامه‌نویسی است که بر پایه مفهوم "شیء" بنا شده و هدف آن سازماندهی کد به شکلی ماژولار، قابل نگهداری، قابل توسعه و قابل استفاده مجدد است. چهار اصل اساسی OOP عبارتند از: Encapsulation (کپسوله‌سازی)، Inheritance (وراثت)، Polymorphism (چندریختی) و Abstraction (انتزاع).

۱. کلاس‌ها و اشیاء (Classes and Objects)

در OOP، کلاس (Class) به عنوان یک الگو، طرح اولیه یا نقشه برای ایجاد اشیاء (Objects) عمل می‌کند. کلاس، ویژگی‌ها (Properties/Fields) و رفتارها (Methods) را تعریف می‌کند. شیء (Object) یک نمونه (Instance) از یک کلاس است. می‌توانید چندین شیء از یک کلاس ایجاد کنید که هر یک دارای وضعیت مستقل خود (مقادیر ویژگی‌ها) باشند.

تعریف کلاس:

public class Car
{
    // ویژگی ها (Fields یا Properties)
    public string Make;    // برند خودرو
    public string Model;   // مدل خودرو
    public int Year;       // سال ساخت
    public string Color;   // رنگ خودرو

    // متد (رفتار)
    public void StartEngine()
    {
        Console.WriteLine($"{Make} {Model} موتور خود را روشن کرد.");
    }

    public void Drive(int speed)
    {
        Console.WriteLine($"{Make} {Model} با سرعت {speed} کیلومتر بر ساعت در حال حرکت است.");
    }
}

ایجاد شیء (Object Instantiation):

برای ایجاد یک شیء از کلاس `Car`، از کلمه کلیدی `new` استفاده می‌کنیم:

// ایجاد یک شیء از کلاس Car
Car myCar = new Car(); 

// مقداردهی به ویژگی های شیء
myCar.Make = "تویوتا";
myCar.Model = "کمری";
myCar.Year = 2020;
myCar.Color = "سفید";

// فراخوانی متدهای شیء
myCar.StartEngine(); // خروجی: تویوتا کمری موتور خود را روشن کرد.
myCar.Drive(100);    // خروجی: تویوتا کمری با سرعت 100 کیلومتر بر ساعت در حال حرکت است.

Car anotherCar = new Car(); // ایجاد شیء دیگری از کلاس Car
anotherCar.Make = "بنز";
anotherCar.Model = "C200";
anotherCar.Year = 2023;
anotherCar.Color = "مشکی";
anotherCar.StartEngine(); // خروجی: بنز C200 موتور خود را روشن کرد.

سازنده‌ها (Constructors):

سازنده‌ها متدهای خاصی هستند که هنگام ایجاد یک شیء (با `new`) فراخوانی می‌شوند. از آن‌ها برای مقداردهی اولیه ویژگی‌های شیء استفاده می‌شود. نام سازنده باید دقیقاً با نام کلاس یکسان باشد و نوع بازگشتی ندارد.

public class Person
{
    public string FirstName { get; set; } // Property
    public string LastName { get; set; }

    // سازنده بدون پارامتر (Default Constructor)
    public Person()
    {
        FirstName = "ناشناس";
        LastName = "ناشناس";
        Console.WriteLine("یک شیء Person بدون پارامتر ایجاد شد.");
    }

    // سازنده با پارامتر (Parameterized Constructor)
    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
        Console.WriteLine($"شیء Person برای {firstName} {lastName} ایجاد شد.");
    }

    // مثال از Property با get/set کامل
    private int _age;
    public int Age
    {
        get { return _age; }
        set 
        {
            if (value >= 0) _age = value;
            else Console.WriteLine("سن نمی تواند منفی باشد!");
        }
    }

    public void DisplayInfo()
    {
        Console.WriteLine($"نام: {FirstName} {LastName}, سن: {Age}");
    }
}

// استفاده از سازنده‌ها:
Person p1 = new Person(); // فراخوانی سازنده بدون پارامتر
p1.DisplayInfo(); // نام: ناشناس ناشناس, سن: 0

Person p2 = new Person("سارا", "رضایی"); // فراخوانی سازنده با پارامتر
p2.Age = 25;
p2.DisplayInfo(); // نام: سارا رضایی, سن: 25

اعضای `static`:

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

public class MathHelper
{
    public static double PI = 3.14159; // فیلد static

    public static int Add(int x, int y) // متد static
    {
        return x + y;
    }
}

// استفاده از اعضای static
Console.WriteLine(MathHelper.PI); // 3.14159
Console.WriteLine(MathHelper.Add(5, 7)); // 12

۲. کپسوله‌سازی (Encapsulation)

کپسوله‌سازی به معنی پنهان کردن جزئیات پیاده‌سازی داخلی یک کلاس و نمایش تنها رابط (Interface) مورد نیاز برای تعامل با آن است. این کار به افزایش امنیت، خوانایی و قابلیت نگهداری کد کمک می‌کند. در C#، کپسوله‌سازی عمدتاً با استفاده از **Access Modifiers (محدودکننده‌های دسترسی)** و **Properties** پیاده‌سازی می‌شود.

محدودکننده‌های دسترسی:

  • `public`: قابل دسترسی از هر کجا.
  • `private`: فقط از داخل همان کلاس قابل دسترسی است. (پیش‌فرض برای اعضای کلاس)
  • `protected`: فقط از داخل همان کلاس و کلاس‌های مشتق شده (فرزند) قابل دسترسی است.
  • `internal`: فقط از داخل همان اسمبلی (پروژه) قابل دسترسی است.
  • `protected internal`: قابل دسترسی از داخل همان اسمبلی یا از کلاس‌های مشتق شده در اسمبلی دیگر.
  • `private protected`: قابل دسترسی فقط از داخل همان کلاس یا کلاس‌های مشتق شده در همان اسمبلی.
public class BankAccount
{
    private decimal _balance; // فیلد private: از بیرون قابل دسترسی نیست

    // Property: راهی کنترل شده برای دسترسی به فیلد private
    public decimal Balance 
    { 
        get { return _balance; } // فقط خواندنی (read-only)
        private set { _balance = value; } // فقط قابل تنظیم از داخل کلاس
    }

    public string AccountNumber { get; private set; } // Auto-implemented property با private setter

    public BankAccount(string accountNumber, decimal initialBalance)
    {
        AccountNumber = accountNumber;
        Balance = initialBalance; // مقداردهی اولیه از طریق setter داخلی
    }

    public void Deposit(decimal amount) // متد public
    {
        if (amount > 0)
        {
            Balance += amount;
            Console.WriteLine($"واریز {amount} انجام شد. موجودی جدید: {Balance}");
        }
    }

    public bool Withdraw(decimal amount) // متد public
    {
        if (amount > 0 && Balance >= amount)
        {
            Balance -= amount;
            Console.WriteLine($"برداشت {amount} انجام شد. موجودی جدید: {Balance}");
            return true;
        }
        Console.WriteLine("برداشت ناموفق: موجودی کافی نیست یا مبلغ نامعتبر است.");
        return false;
    }
}

// استفاده:
BankAccount myAccount = new BankAccount("123456789", 1000);
Console.WriteLine(myAccount.Balance); // 1000 (دسترسی از طریق getter)
// myAccount.Balance = 500; // خطا: setter private است
myAccount.Deposit(200); // واریز 200 انجام شد. موجودی جدید: 1200
myAccount.Withdraw(500); // برداشت 500 انجام شد. موجودی جدید: 700
myAccount.Withdraw(1000); // برداشت ناموفق: موجودی کافی نیست یا مبلغ نامعتبر است.

۳. وراثت (Inheritance)

وراثت به یک کلاس اجازه می‌دهد تا ویژگی‌ها و رفتارهای یک کلاس دیگر را به ارث ببرد. این مفهوم باعث استفاده مجدد از کد (Code Reusability) و ایجاد سلسله‌مراتب (Hierarchy) بین کلاس‌ها می‌شود. کلاسی که به ارث می‌برد، "کلاس مشتق شده" (Derived Class) یا "کلاس فرزند" (Child Class) نامیده می‌شود و کلاسی که به ارث داده می‌شود، "کلاس پایه" (Base Class) یا "کلاس والد" (Parent Class) نامیده می‌شود.

public class Animal // کلاس پایه
{
    public string Name { get; set; }
    public int Age { get; set; }

    public Animal(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public void Eat()
    {
        Console.WriteLine($"{Name} غذا می خورد.");
    }

    public virtual void MakeSound() // virtual: متد را قابل Overriding می کند
    {
        Console.WriteLine($"{Name} صدایی تولید می کند.");
    }
}

public class Dog : Animal // کلاس Dog از Animal ارث می برد
{
    public string Breed { get; set; }

    public Dog(string name, int age, string breed) : base(name, age) // فراخوانی سازنده کلاس پایه
    {
        Breed = breed;
    }

    public void Fetch()
    {
        Console.WriteLine($"{Name} در حال آوردن توپ است.");
    }

    public override void MakeSound() // override: پیاده سازی متد virtual کلاس پایه را تغییر می دهد
    {
        Console.WriteLine($"{Name} هاپ هاپ می کند.");
    }
}

public class Cat : Animal // کلاس Cat از Animal ارث می برد
{
    public Cat(string name, int age) : base(name, age) { }

    public override void MakeSound()
    {
        Console.WriteLine($"{Name} میو میو می کند.");
    }
}

// استفاده از وراثت:
Dog myDog = new Dog("لوسی", 3, "ژرمن شپرد");
myDog.Eat();       // لوسی غذا می خورد. (متد از Animal)
myDog.MakeSound(); // لوسی هاپ هاپ می کند. (متد از Dog - Overridden)
myDog.Fetch();     // لوسی در حال آوردن توپ است. (متد مخصوص Dog)

Cat myCat = new Cat("پرنسس", 5);
myCat.Eat();       // پرنسس غذا می خورد.
myCat.MakeSound(); // پرنسس میو میو می کند.

۴. چندریختی (Polymorphism)

چندریختی به معنی "اشکال مختلف" است. در OOP، به معنای قابلیت اشیاء مختلف برای پاسخگویی به یک فراخوانی متد به روش‌های متفاوت است. دو نوع اصلی چندریختی در C# وجود دارد:

  • Compile-time Polymorphism (سربارگذاری متد - Method Overloading): قبلاً توضیح داده شد (متدهای با نام یکسان و پارامترهای متفاوت).
  • Run-time Polymorphism (بازنویسی متد - Method Overriding): از طریق وراثت و کلمات کلیدی `virtual` و `override` به دست می‌آید. به شیء والد امکان می‌دهد ارجاعی به یک شیء فرزند داشته باشد و هنگام فراخوانی یک متد `virtual`، نسخه `override` شده در زمان اجرا فراخوانی شود.
// ادامه مثال Animal و Dog/Cat
Animal[] animals = new Animal[3];
animals[0] = new Dog("بابی", 2, "پودل");
animals[1] = new Cat("سانی", 4);
animals[2] = new Animal("تایگر", 6); // می تواند یک شیء Animal نیز باشد

foreach (Animal animal in animals)
{
    animal.MakeSound(); // در زمان اجرا مشخص می شود که کدام MakeSound فراخوانی شود
}
// خروجی:
// بابی هاپ هاپ می کند.
// سانی میو میو می کند.
// تایگر صدایی تولید می کند.

کلاس‌های انتزاعی (Abstract Classes) و متدهای انتزاعی (Abstract Methods):

یک کلاس `abstract` نمی‌تواند به طور مستقیم نمونه‌سازی شود (یعنی نمی‌توانید از آن شیء بسازید). هدف آن فراهم کردن یک پایه مشترک برای کلاس‌های مشتق شده است. کلاس‌های انتزاعی می‌توانند هم متدهای عادی (با بدنه) و هم متدهای انتزاعی (فقط تعریف، بدون بدنه) داشته باشند. متدهای انتزاعی باید در کلاس‌های فرزند غیرانتزاعی (`concrete`) حتماً پیاده‌سازی شوند.

public abstract class Shape // کلاس انتزاعی
{
    public abstract double GetArea(); // متد انتزاعی: بدون بدنه، باید توسط کلاس های فرزند پیاده سازی شود

    public void Display() // متد عادی
    {
        Console.WriteLine($"این یک شکل با مساحت {GetArea()} است.");
    }
}

public class Circle : Shape
{
    public double Radius { get; set; }

    public Circle(double radius)
    {
        Radius = radius;
    }

    public override double GetArea() // پیاده سازی متد انتزاعی
    {
        return Math.PI * Radius * Radius;
    }
}

public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }

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

    public override double GetArea() // پیاده سازی متد انتزاعی
    {
        return Width * Height;
    }
}

// استفاده:
// Shape s = new Shape(); // خطا: نمی توان از کلاس انتزاعی شیء ساخت
Shape circle = new Circle(5);
Console.WriteLine(circle.GetArea()); // 78.539...
circle.Display(); // این یک شکل با مساحت 78.539... است.

Shape rectangle = new Rectangle(4, 5);
Console.WriteLine(rectangle.GetArea()); // 20

اینترفیس‌ها (Interfaces):

اینترفیس‌ها، یک "قرارداد" را تعریف می‌کنند؛ مجموعه‌ای از متدها، ویژگی‌ها، رویدادها یا ایندکسرها (بدون پیاده‌سازی) که یک کلاس می‌تواند آن‌ها را پیاده‌سازی کند. یک کلاس می‌تواند از چندین اینترفیس ارث ببرد، که این قابلیت چندوراثتی (Multiple Inheritance) را که در C# برای کلاس‌ها پشتیبانی نمی‌شود، شبیه‌سازی می‌کند. اینترفیس‌ها با کلمه کلیدی `interface` تعریف می‌شوند.

public interface IDrawable // اینترفیس
{
    void Draw(); // تعریف متد بدون بدنه
    string GetColor(); // تعریف متد با بازگشتی
}

public class Square : IDrawable
{
    public string Color { get; set; }

    public Square(string color)
    {
        Color = color;
    }

    public void Draw() // پیاده سازی متد Draw از اینترفیس
    {
        Console.WriteLine($"یک مربع {Color} رسم شد.");
    }

    public string GetColor() // پیاده سازی متد GetColor از اینترفیس
    {
        return Color;
    }
}

public class Triangle : IDrawable
{
    public string Color { get; set; }

    public Triangle(string color)
    {
        Color = color;
    }

    public void Draw()
    {
        Console.WriteLine($"یک مثلث {Color} رسم شد.");
    }

    public string GetColor()
    {
        return Color;
    }
}

// استفاده:
IDrawable[] shapes = new IDrawable[2];
shapes[0] = new Square("قرمز");
shapes[1] = new Triangle("آبی");

foreach (IDrawable shape in shapes)
{
    shape.Draw(); // Polymorphism با اینترفیس
    Console.WriteLine($"رنگ: {shape.GetColor()}");
}
// خروجی:
// یک مربع قرمز رسم شد.
// رنگ: قرمز
// یک مثلث آبی رسم شد.
// رنگ: آبی

تفاوت اصلی بین کلاس‌های انتزاعی و اینترفیس‌ها در این است که کلاس انتزاعی می‌تواند پیاده‌سازی داشته باشد و برای کلاس‌هایی که "یک نوع از" چیزی هستند (is-a relationship) استفاده می‌شود، در حالی که اینترفیس‌ها فقط قرارداد را تعریف می‌کنند و برای کلاس‌هایی که "می‌توانند کاری را انجام دهند" (can-do relationship) به کار می‌روند.

۵. انتزاع (Abstraction)

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

با تسلط بر این چهار اصل OOP، شما قادر خواهید بود نرم‌افزارهای پیچیده‌تر، قابل نگهداری‌تر و مقیاس‌پذیرتری را در C# طراحی و پیاده‌سازی کنید. این مباحث ستون فقرات هر پروژه حرفه‌ای در C# هستند.

مفاهیم پیشرفته C#: از کالکشن‌ها تا برنامه‌نویسی غیرهمزمان

پس از تسلط بر اصول برنامه‌نویسی شیءگرا، زمان آن رسیده است که به برخی از مفاهیم پیشرفته‌تر در C# بپردازیم. این مباحث به شما کمک می‌کنند تا کدی کارآمدتر، پایدارتر و با کارایی بالاتر بنویسید.

۱. کالکشن‌ها و جنریک‌ها (Collections and Generics)

تاکنون با آرایه‌ها آشنا شده‌ایم که برای نگهداری مجموعه‌ای از داده‌ها کاربرد دارند. اما آرایه‌ها دارای اندازه‌ای ثابت هستند که پس از ایجاد نمی‌توان آن را تغییر داد. کالکشن‌ها (Collections) ساختارهای داده‌ای انعطاف‌پذیرتری را فراهم می‌کنند که می‌توانند به صورت پویا رشد یا کوچک شوند. جنریک‌ها (Generics) به ما امکان می‌دهند تا کلاس‌ها، متدها و اینترفیس‌ها را به گونه‌ای بنویسیم که بتوانند با هر نوع داده‌ای کار کنند، بدون اینکه نوع داده خاصی را در زمان کامپایل مشخص کنند، که این امر منجر به کدنویسی امن‌تر و با کارایی بالاتر می‌شود.

کالکشن‌های جنریک (`System.Collections.Generic`):

  • `List`: یک لیست پویا از اشیاء. می‌توانید به راحتی عناصر را اضافه، حذف یا به آن‌ها دسترسی پیدا کنید. `T` نوع داده‌ای است که لیست نگهداری می‌کند.
    List<string> names = new List<string>();
    names.Add("علی");
    names.Add("سارا");
    names.Add("رضا");
    Console.WriteLine(names[1]); // سارا
    names.Remove("علی");
    Console.WriteLine(names.Count); // 2
    
  • `Dictionary`: مجموعه‌ای از جفت‌های کلید/مقدار (Key/Value). هر کلید باید منحصر به فرد باشد.
    Dictionary<int, string> students = new Dictionary<int, string>();
    students.Add(1, "مینا");
    students.Add(2, "بهزاد");
    Console.WriteLine(students[1]); // مینا
    
    if (students.ContainsKey(3))
    {
        Console.WriteLine(students[3]);
    }
    else
    {
        Console.WriteLine("دانش آموز با کد 3 یافت نشد.");
    }
    
    foreach (var student in students)
    {
        Console.WriteLine($"کد: {student.Key}, نام: {student.Value}");
    }
    
  • `HashSet`: مجموعه‌ای از عناصر منحصر به فرد (بدون تکرار)، بدون ترتیب خاص. برای بررسی وجود یک عنصر بسیار کارآمد است.
    HashSet<string> uniqueFruits = new HashSet<string>();
    uniqueFruits.Add("سیب");
    uniqueFruits.Add("پرتقال");
    uniqueFruits.Add("سیب"); // این عنصر اضافه نمی شود چون تکراری است
    Console.WriteLine(uniqueFruits.Contains("سیب")); // True
    Console.WriteLine(uniqueFruits.Count); // 2
    
  • `Queue`: یک صف (First-In, First-Out - FIFO). اولین عنصری که اضافه می‌شود، اولین عنصری است که حذف می‌شود.
    Queue<string> tasks = new Queue<string>();
    tasks.Enqueue("Task 1"); // اضافه کردن به صف
    tasks.Enqueue("Task 2");
    Console.WriteLine(tasks.Dequeue()); // Task 1 (حذف و بازگرداندن اولین عنصر)
    
  • `Stack`: یک پشته (Last-In, First-Out - LIFO). آخرین عنصری که اضافه می‌شود، اولین عنصری است که حذف می‌شود.
    Stack<int> numbers = new Stack<int>();
    numbers.Push(10); // اضافه کردن به پشته
    numbers.Push(20);
    Console.WriteLine(numbers.Pop()); // 20 (حذف و بازگرداندن آخرین عنصر)
    

جنریک‌ها (Generics):

هدف اصلی جنریک‌ها، فعال کردن مجدد استفاده از کد بدون قربانی کردن ایمنی نوع یا کارایی است. به جای نوشتن چندین متد برای انواع داده‌های مختلف، می‌توانید یک متد جنریک بنویسید که با `T` (نوع عمومی) کار کند.

public class GenericBox<T> // کلاس جنریک
{
    public T Value { get; set; }
}

public class Utility
{
    public static void Swap<T>(ref T a, ref T b) // متد جنریک
    {
        T temp = a;
        a = b;
        b = temp;
    }
}

// استفاده:
GenericBox<int> intBox = new GenericBox<int> { Value = 123 };
GenericBox<string> stringBox = new GenericBox<string> { Value = "سلام" };

Console.WriteLine(intBox.Value);    // 123
Console.WriteLine(stringBox.Value); // سلام

int x = 1, y = 2;
Utility.Swap<int>(ref x, ref y);
Console.WriteLine($"x: {x}, y: {y}"); // x: 2, y: 1

۲. مدیریت خطا (Exception Handling)

خطاها (Errors) و استثناها (Exceptions) شرایط غیرمنتظره‌ای هستند که در زمان اجرای برنامه رخ می‌دهند و می‌توانند منجر به از کار افتادن برنامه شوند. C# یک مکانیزم قوی برای مدیریت استثناها با استفاده از بلوک‌های `try-catch-finally` فراهم می‌کند.

  • `try`: بلوکی از کد که ممکن است استثنا ایجاد کند.
  • `catch`: بلوکی که اگر استثنایی در بلوک `try` رخ دهد، اجرا می‌شود. می‌توانید چندین بلوک `catch` برای مدیریت انواع مختلف استثنا داشته باشید.
  • `finally`: بلوکی که همیشه اجرا می‌شود، چه استثنایی رخ دهد و چه ندهد. اغلب برای پاکسازی منابع (مانند بستن فایل‌ها یا اتصالات پایگاه داده) استفاده می‌شود.
try
{
    Console.Write("عدد اول را وارد کنید: ");
    int num1 = Convert.ToInt32(Console.ReadLine());

    Console.Write("عدد دوم را وارد کنید: ");
    int num2 = Convert.ToInt32(Console.ReadLine());

    int result = num1 / num2; // ممکن است DivideByZeroException رخ دهد
    Console.WriteLine($"نتیجه تقسیم: {result}");

    string[] names = { "الف", "ب" };
    Console.WriteLine(names[2]); // ممکن است IndexOutOfRangeException رخ دهد
}
catch (DivideByZeroException ex) // گرفتن استثنای خاص
{
    Console.WriteLine("خطا: نمی‌توانید بر صفر تقسیم کنید.");
    Console.WriteLine($"جزئیات خطا: {ex.Message}");
}
catch (FormatException ex) // گرفتن استثنای دیگر
{
    Console.WriteLine("خطا: ورودی نامعتبر است. لطفا یک عدد صحیح وارد کنید.");
    Console.WriteLine($"جزئیات خطا: {ex.Message}");
}
catch (IndexOutOfRangeException ex)
{
    Console.WriteLine("خطا: دسترسی به اندیس خارج از محدوده آرایه.");
    Console.WriteLine($"جزئیات خطا: {ex.Message}");
}
catch (Exception ex) // گرفتن هر نوع استثنای دیگر (باید آخرین catch باشد)
{
    Console.WriteLine($"یک خطای ناشناخته رخ داد: {ex.Message}");
}
finally
{
    Console.WriteLine("بلوک finally همیشه اجرا می‌شود (پاکسازی منابع).");
}

`throw` Keyword: می‌توانید استثناهای خود را با استفاده از کلمه کلیدی `throw` پرتاب کنید.

public void ProcessPayment(decimal amount)
{
    if (amount <= 0)
    {
        throw new ArgumentException("مبلغ پرداخت باید مثبت باشد.");
    }
    // ادامه منطق پرداخت
    Console.WriteLine($"پرداخت به مبلغ {amount} با موفقیت انجام شد.");
}
// استفاده:
try
{
    ProcessPayment(-100);
}
catch (ArgumentException ex)
{
    Console.WriteLine($"خطا در پرداخت: {ex.Message}");
}

۳. دلیگیت‌ها و رویدادها (Delegates and Events)

دلیگیت (Delegate) یک نوع اشاره‌گر امن به متد است. آن‌ها به شما اجازه می‌دهند متدها را به عنوان آرگومان به متدهای دیگر ارسال کنید یا چندین متد را به یک فراخوانی (Multicast Delegate) متصل کنید. دلیگیت‌ها پایه و اساس پیاده‌سازی **رویدادها (Events)** در C# هستند.

// تعریف یک دلیگیت
public delegate void MyDelegate(string message);

public class Messenger
{
    public void SendMessage(string msg)
    {
        Console.WriteLine($"پیام ارسال شد: {msg}");
    }

    public static void LogMessage(string msg)
    {
        Console.WriteLine($"پیام لاگ شد: {msg}");
    }
}

// استفاده از دلیگیت:
MyDelegate del1 = new MyDelegate(new Messenger().SendMessage);
MyDelegate del2 = Messenger.LogMessage; // برای متدهای static نیازی به new نیست

del1("سلام به همه!"); // فراخوانی متد SendMessage
del2("یک پیام مهم!"); // فراخوانی متد LogMessage

// دلیگیت Multicast:
MyDelegate multicastDel = del1 + del2; // اضافه کردن متدها به دلیگیت
multicastDel("پیام Multicast!");
// خروجی:
// پیام ارسال شد: پیام Multicast!
// پیام لاگ شد: پیام Multicast!

رویدادها (Events): رویدادها مکانیزمی برای ارتباط بین اشیاء هستند که به یک شیء (Publisher) اجازه می‌دهد به سایر اشیاء (Subscribers) اطلاع دهد که اتفاق خاصی رخ داده است. رویدادها بر پایه دلیگیت‌ها بنا شده‌اند و اغلب با `EventHandler` و `EventArgs` استفاده می‌شوند.

public class Button
{
    // تعریف رویداد با استفاده از EventHandler
    public event EventHandler Click; 

    public void SimulateClick()
    {
        Console.WriteLine("دکمه فشرده شد.");
        // فراخوانی رویداد: اگر کسی به آن گوش می دهد (null نیست)
        OnClick(EventArgs.Empty); 
    }

    // متد محافظت شده برای فعال کردن رویداد
    protected virtual void OnClick(EventArgs e)
    {
        Click?.Invoke(this, e); // استفاده از null-conditional operator
    }
}

public class MyForm
{
    public MyForm()
    {
        Button btn = new Button();
        btn.Click += Button_Click; // اشتراک در رویداد (اضافه کردن Event Handler)
        btn.SimulateClick();
    }

    private void Button_Click(object sender, EventArgs e) // Event Handler
    {
        Console.WriteLine("متد Button_Click فراخوانی شد!");
    }
}

// برای اجرای مثال بالا در Main:
// MyForm form = new MyForm();

۴. LINQ (Language Integrated Query)

LINQ مجموعه‌ای از قابلیت‌ها در C# است که به شما امکان می‌دهد از داخل کد C#، به روشی یکپارچه و خوانا، داده‌ها را از منابع مختلف (مانند مجموعه‌ها، پایگاه‌های داده، XML و ...) بازیابی و دستکاری کنید. LINQ از سینتکس SQL-مانند یا متدهای توسعه (Extension Methods) استفاده می‌کند.

مثال با Query Syntax:

List<int> numbers = new List<int> { 5, 10, 8, 20, 15, 7 };

// انتخاب اعداد زوج و مرتب سازی آنها
var evenNumbers = from num in numbers
                  where num % 2 == 0
                  orderby num descending
                  select num;

Console.WriteLine("اعداد زوج به ترتیب نزولی:");
foreach (int num in evenNumbers)
{
    Console.WriteLine(num); // 20, 10, 8
}

مثال با Method Syntax (Extension Methods):

List<string> names = new List<string> { "علی", "زهرا", "محمد", "سارا" };

// انتخاب نام هایی که با 'س' شروع می شوند و به حروف بزرگ تبدیل می شوند
var filteredNames = names.Where(n => n.StartsWith("س"))
                         .OrderBy(n => n)
                         .Select(n => n.ToUpper());

Console.WriteLine("نام های فیلتر شده:");
foreach (string name in filteredNames)
{
    Console.WriteLine(name); // سارا
}

LINQ عملیات‌های رایجی مانند فیلتر کردن (`Where`), مرتب‌سازی (`OrderBy`), انتخاب (`Select`), گروه‌بندی (`GroupBy`) و تجمیع (`Count`, `Sum`, `Average`) را بسیار ساده می‌کند.

۵. کار با فایل‌ها (File I/O)

C# از طریق فضای نام `System.IO` امکانات گسترده‌ای برای کار با فایل‌ها و دایرکتوری‌ها فراهم می‌کند. شما می‌توانید فایل‌ها را بخوانید، بنویسید، کپی کنید، حذف کنید و اطلاعات مربوط به آن‌ها را به دست آورید.

string filePath = "mydata.txt";
string directoryPath = "MyFolder";

// نوشتن در یک فایل متنی
try
{
    File.WriteAllText(filePath, "این اولین خط است.\n");
    File.AppendAllText(filePath, "این خط دوم است.\n");
    Console.WriteLine("فایل با موفقیت نوشته شد.");
}
catch (Exception ex)
{
    Console.WriteLine($"خطا در نوشتن فایل: {ex.Message}");
}

// خواندن از یک فایل متنی
try
{
    string content = File.ReadAllText(filePath);
    Console.WriteLine("محتوای فایل:");
    Console.WriteLine(content);
}
catch (FileNotFoundException)
{
    Console.WriteLine("فایل یافت نشد.");
}
catch (Exception ex)
{
    Console.WriteLine($"خطا در خواندن فایل: {ex.Message}");
}

// ایجاد دایرکتوری
if (!Directory.Exists(directoryPath))
{
    Directory.CreateDirectory(directoryPath);
    Console.WriteLine($"دایرکتوری '{directoryPath}' ایجاد شد.");
}

// حذف فایل
// File.Delete(filePath);
// Console.WriteLine("فایل حذف شد.");

برای کار با فایل‌های بزرگ یا زمانی که نیاز به کنترل دقیق‌تری بر عملیات خواندن/نوشتن دارید، می‌توانید از `StreamReader` و `StreamWriter` استفاده کنید. همیشه از بلوک `using` برای اطمینان از بسته شدن صحیح منابع فایل استفاده کنید.

using (StreamWriter writer = new StreamWriter("log.txt"))
{
    writer.WriteLine("این یک پیام لاگ است.");
    writer.WriteLine("زمان: " + DateTime.Now);
} // writer به طور خودکار در اینجا بسته می شود

using (StreamReader reader = new StreamReader("log.txt"))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        Console.WriteLine(line);
    }
}

۶. برنامه‌نویسی غیرهمزمان (Asynchronous Programming) با `async`/`await`

در برنامه‌های مدرن، اغلب نیاز به انجام عملیات‌هایی داریم که زمان‌بر هستند (مانند دسترسی به پایگاه داده، درخواست‌های شبکه، عملیات I/O). اگر این عملیات‌ها به صورت همزمان (Synchronous) اجرا شوند، می‌توانند رابط کاربری را مسدود کرده و برنامه را غیرقابل پاسخگویی کنند. برنامه‌نویسی غیرهمزمان (Asynchronous Programming) به برنامه اجازه می‌دهد تا بدون انتظار برای اتمام یک عملیات طولانی، به کار خود ادامه دهد.

در C#، این کار با استفاده از کلمات کلیدی `async` و `await` و نوع `Task` انجام می‌شود.

  • `async`: یک متد را به عنوان یک متد غیرهمزمان علامت‌گذاری می‌کند. متد `async` معمولاً `Task` یا `Task` را برمی‌گرداند.
  • `await`: اجرای متد `async` را به طور موقت متوقف می‌کند تا زمانی که عملیات غیرهمزمان تکمیل شود، بدون اینکه Thread اصلی را مسدود کند. پس از اتمام عملیات، اجرای متد از همان نقطه `await` از سر گرفته می‌شود.
public class WebDownloader
{
    // متد شبیه سازی شده برای دانلود یک صفحه وب
    public async Task<string> DownloadWebPageAsync(string url)
    {
        Console.WriteLine($"شروع دانلود از {url}...");
        // شبیه سازی یک عملیات زمان بر با تاخیر 3 ثانیه
        await Task.Delay(3000); 
        Console.WriteLine($"پایان دانلود از {url}.");
        return $"محتوای صفحه از {url}";
    }

    // متد اصلی برنامه (مثلاً در یک برنامه Console یا UI)
    public async Task RunDownload()
    {
        Console.WriteLine("برنامه شروع به کار کرد.");

        // فراخوانی متد غیرهمزمان
        Task<string> downloadTask = DownloadWebPageAsync("http://example.com");

        Console.WriteLine("در حین دانلود، کارهای دیگر در حال انجام است...");
        // اینجا می توانید کدهای دیگر را اجرا کنید که به نتیجه دانلود بستگی ندارند

        string content = await downloadTask; // منتظر اتمام دانلود می مانیم
        Console.WriteLine($"محتوای دریافتی: {content.Substring(0, 20)}...");

        Console.WriteLine("برنامه به پایان رسید.");
    }
}

// برای اجرای مثال در متد Main:
// static async Task Main(string[] args)
// {
//     WebDownloader downloader = new WebDownloader();
//     await downloader.RunDownload();
//     Console.ReadKey(); // برای نگه داشتن پنجره کنسول
// }

برنامه‌نویسی غیرهمزمان یک مهارت حیاتی برای توسعه برنامه‌های مدرن و پاسخگو است، به ویژه در برنامه‌های دسکتاپ، وب و موبایل که تجربه کاربری از اهمیت بالایی برخوردار است.

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

ساخت اولین پروژه‌های عملی با C#: کاربردهای واقعی آموخته‌ها

تئوری بدون عمل، ناقص است. برای تثبیت آموخته‌هایتان و درک واقعی کاربرد C#، ساخت پروژه‌های عملی ضروری است. در این بخش، به چند مثال ساده از پروژه‌هایی که می‌توانید با مهارت‌های کسب کرده خود بسازید، می‌پردازیم و چشم‌اندازی از پلتفرم‌هایی که می‌توانید با C# برای آنها توسعه دهید، ارائه می‌دهیم.

پروژه‌های کنسول ساده:

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

۱. ماشین حساب ساده:

یک ماشین حساب که عملیات اصلی (جمع، تفریق، ضرب، تقسیم) را انجام دهد.

  • از `Console.ReadLine()` برای گرفتن ورودی از کاربر استفاده کنید.
  • از `Convert.ToDouble()` یا `double.Parse()` برای تبدیل ورودی‌های رشته‌ای به اعداد استفاده کنید.
  • از `if-else if-else` یا `switch` برای انتخاب عملیات استفاده کنید.
  • از مدیریت خطا (`try-catch`) برای جلوگیری از از کار افتادن برنامه هنگام ورود داده‌های نامعتبر یا تقسیم بر صفر استفاده کنید.
public class SimpleCalculator
{
    public static void Run()
    {
        while (true)
        {
            Console.WriteLine("\n--- ماشین حساب ساده ---");
            Console.WriteLine("عملیات را انتخاب کنید:");
            Console.WriteLine("1. جمع (+)");
            Console.WriteLine("2. تفریق (-)");
            Console.WriteLine("3. ضرب (*)");
            Console.WriteLine("4. تقسیم (/)");
            Console.WriteLine("5. خروج");
            Console.Write("انتخاب شما: ");
            string choice = Console.ReadLine();

            if (choice == "5")
            {
                Console.WriteLine("خداحافظ!");
                break;
            }

            if (!double.TryParse(Console.ReadLine(), out double num1) ||
                !double.TryParse(Console.ReadLine(), out double num2))
            {
                Console.WriteLine("ورودی نامعتبر. لطفا عدد وارد کنید.");
                continue;
            }
            
            double result = 0;
            bool isValidOperation = true;

            switch (choice)
            {
                case "1": result = num1 + num2; break;
                case "2": result = num1 - num2; break;
                case "3": result = num1 * num2; break;
                case "4":
                    if (num2 == 0)
                    {
                        Console.WriteLine("خطا: تقسیم بر صفر مجاز نیست.");
                        isValidOperation = false;
                    }
                    else
                    {
                        result = num1 / num2;
                    }
                    break;
                default:
                    Console.WriteLine("انتخاب نامعتبر است. دوباره امتحان کنید.");
                    isValidOperation = false;
                    break;
            }

            if (isValidOperation)
            {
                Console.WriteLine($"نتیجه: {result}");
            }
        }
    }
}

۲. مدیریت لیست وظایف (To-Do List Manager):

یک برنامه ساده برای اضافه کردن، نمایش، حذف و علامت‌گذاری وظایف.

  • از `List` برای ذخیره وظایف استفاده کنید.
  • از حلقه‌ها و دستورات شرطی برای ساخت منوی تعاملی استفاده کنید.
  • می‌توانید برای پیشرفته‌تر شدن، وظایف را در یک فایل متنی ذخیره و بارگذاری کنید (`File.ReadAllLines`, `File.WriteAllLines`).
  • می‌توانید برای هر وظیفه، کلاسی جداگانه (`Task` با ویژگی‌های `Description`, `IsCompleted`) تعریف کنید و از `List` استفاده کنید.

نگاهی اجمالی به پلتفرم‌های توسعه با C#

همانطور که پیش‌تر ذکر شد، C# یک زبان بسیار انعطاف‌پذیر است و برای توسعه در پلتفرم‌های مختلف استفاده می‌شود. در اینجا به معرفی کوتاهی از مهم‌ترین آن‌ها می‌پردازیم:

۱. توسعه دسکتاپ: WinForms و WPF

  • Windows Forms (WinForms): قدیمی‌تر و ساده‌تر است. برای ساخت برنامه‌های کاربردی دسکتاپ ویندوز با رابط کاربری مبتنی بر کنترل‌های استاندارد ویندوز مناسب است. یادگیری آن برای شروع راحت‌تر است.
  • Windows Presentation Foundation (WPF): مدرن‌تر و قدرتمندتر است. از XAML (زبان نشانه‌گذاری توسعه‌پذیر برنامه) برای طراحی رابط کاربری استفاده می‌کند که امکان ساخت رابط‌های کاربری بسیار غنی و سفارشی را فراهم می‌کند. برای برنامه‌های با پیچیدگی بصری بالا توصیه می‌شود.

در Visual Studio، هنگام ایجاد پروژه جدید، می‌توانید قالب "WPF Application" یا "Windows Forms App" را انتخاب کنید.

۲. توسعه وب: ASP.NET Core

ASP.NET Core فریم‌ورک متن‌باز و کراس‌پلتفرم مایکروسافت برای ساخت برنامه‌های وب مدرن است.

  • ASP.NET Core MVC (Model-View-Controller): یک الگوی معماری محبوب برای ساخت وب‌اپلیکیشن‌هایی که منطق، نمایش و داده‌ها را جدا می‌کنند.
  • Razor Pages: برای ساخت برنامه‌های وب ساده‌تر که در آن کد و نشانه گذاری نزدیک‌تر به هم هستند.
  • ASP.NET Core Web API: برای ساخت وب‌سرویس‌های RESTful که توسط فرانت‌اند (مانند React, Angular, Vue) یا سایر برنامه‌ها مصرف می‌شوند.
  • Blazor: یک فریم‌ورک جدید که به شما امکان می‌دهد رابط کاربری تعاملی وب سمت کلاینت را با C# و .NET بسازید، به جای JavaScript.

ASP.NET Core بسیار قدرتمند و مورد تقاضا در بازار کار است و برای ساخت وب‌سایت‌ها و خدمات بک‌اند با کارایی بالا ایده‌آل است.

۳. توسعه موبایل: .NET MAUI (Xamarin سابق)

.NET MAUI (Multi-platform App UI) جانشین Xamarin است و به شما امکان می‌دهد اپلیکیشن‌های بومی را برای iOS، Android، Windows و macOS با استفاده از یک کدبیس واحد C# توسعه دهید. این یک راه عالی برای رسیدن به چندین پلتفرم با تلاش کمتر است.

۴. بازی‌سازی: Unity

Unity یک موتور بازی‌سازی بسیار محبوب است که برای توسعه بازی‌های دو بعدی و سه بعدی در پلتفرم‌های مختلف (PC، کنسول، موبایل) استفاده می‌شود. C# زبان اصلی برنامه‌نویسی اسکریپت‌ها در Unity است. اگر به بازی‌سازی علاقه دارید، یادگیری C# یک گام بزرگ در این مسیر است.

۵. توسعه ابری: Azure Functions، AWS Lambda و ...

C# به طور گسترده‌ای در توسعه سرویس‌های ابری و توابع بدون سرور (Serverless Functions) استفاده می‌شود. می‌توانید منطق تجاری خود را در توابع C# بنویسید و آن‌ها را روی پلتفرم‌های ابری مانند Microsoft Azure Functions یا AWS Lambda مستقر کنید. این رویکرد برای ساخت میکروسرویس‌ها و برنامه‌های مقیاس‌پذیر بسیار محبوب است.

انتخاب پلتفرم به علایق و اهداف شغلی شما بستگی دارد. اما با یادگیری C#، درب‌های بسیاری در تمام این حوزه‌ها به روی شما گشوده خواهد شد.

مسیر یادگیری مداوم و تخصص‌های C#: از اینجا به کجا برویم؟

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

۱. تمرین، تمرین، تمرین!

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

  • حل مسائل برنامه‌نویسی: وب‌سایت‌هایی مانند HackerRank، LeetCode، CodeWars یا TopCoder مسائل برنامه‌نویسی در سطوح مختلف ارائه می‌دهند که به شما کمک می‌کنند منطق خود را تقویت کنید.
  • ساخت پروژه‌های شخصی: ایده‌های کوچک را عملی کنید. یک برنامه مدیریت مخاطبین، یک بازی ساده (مانند حدس اعداد یا سنگ-کاغذ-قیچی)، یا یک ابزار ساده برای نیازهای روزمره خود بسازید. این پروژه‌ها به شما کمک می‌کنند تا با چالش‌های واقعی برنامه‌نویسی مواجه شوید.
  • بازسازی پروژه‌های موجود: سعی کنید پروژه‌های ساده‌ای که قبلاً دیده‌اید را از نو با دانش خود پیاده‌سازی کنید.

۲. مطالعه مستندات رسمی

منابع رسمی مایکروسافت برای C# و .NET بسیار جامع و به‌روز هستند. وب‌سایت Microsoft Learn بهترین مکان برای دسترسی به آموزش‌ها، راهنماها و مستندات عمیق است.

۳. عضویت در جامعه برنامه‌نویسان

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

  • Stack Overflow: برای پرسش و پاسخ در مورد مسائل برنامه‌نویسی.
  • گروه‌های Reddit: مانند r/csharp و r/dotnet برای بحث و تبادل نظر.
  • گروه‌های کاربری محلی: در شهر یا منطقه خود به دنبال گروه‌های برنامه‌نویسان C# باشید و در جلسات آن‌ها شرکت کنید.
  • گیت‌هاب (GitHub): به پروژه‌های متن‌باز بپیوندید یا پروژه‌های خود را در آنجا منتشر کنید. این کار به شما فرصت همکاری و دریافت بازخورد می‌دهد.

۴. مفاهیم پیشرفته‌تر برای یادگیری

هنگامی که احساس راحتی با مفاهیم اصلی کردید، می‌توانید به سراغ موضوعات پیشرفته‌تر بروید:

  • الگوهای طراحی (Design Patterns): مانند Singleton, Factory, Observer, Decorator. این الگوها راه‌حل‌های اثبات‌شده‌ای برای مسائل رایج طراحی نرم‌افزار هستند.
  • تست واحد (Unit Testing): یادگیری نحوه نوشتن تست برای کد خود با استفاده از فریم‌ورک‌هایی مانند NUnit یا xUnit. این کار به افزایش کیفیت و پایداری کد کمک می‌کند.
  • تزریق وابستگی (Dependency Injection - DI): یک الگوی طراحی که به کاهش وابستگی بین اجزای نرم‌افزار کمک می‌کند و قابلیت تست و نگهداری را بهبود می‌بخشد.
  • Entity Framework Core (ORM): برای تعامل با پایگاه‌های داده رابطه‌ای با استفاده از اشیاء C#.
  • میکروسرویس‌ها (Microservices): معماری برای ساخت برنامه‌های کاربردی به عنوان مجموعه‌ای از سرویس‌های کوچک و مستقل.
  • امنیت در برنامه‌های وب: احراز هویت (Authentication)، مجوز (Authorization)، محافظت در برابر حملات XSS و CSRF.
  • مدیریت حافظه پیشرفته و Performance Tuning: درک نحوه عملکرد Garbage Collector، استفاده از Profile‌ها برای یافتن گلوگاه‌ها و بهینه‌سازی کد.
  • برنامه‌نویسی موازی (Parallel Programming): استفاده از Task Parallel Library (TPL) برای بهره‌برداری از هسته‌های پردازنده و انجام عملیات به صورت همزمان.

۵. انتخاب تخصص

با توجه به تنوع کاربردهای C#، می‌توانید در یکی از حوزه‌های زیر تخصص پیدا کنید:

  • توسعه‌دهنده Back-End با ASP.NET Core: تمرکز بر منطق سمت سرور، API‌ها، پایگاه‌های داده.
  • توسعه‌دهنده Front-End با Blazor: اگر به ساخت رابط کاربری با C# علاقه‌مندید.
  • توسعه‌دهنده دسکتاپ (WPF): برای ساخت برنامه‌های کاربردی ویندوز.
  • توسعه‌دهنده موبایل (.NET MAUI): برای ساخت اپلیکیشن‌های iOS و Android.
  • توسعه‌دهنده بازی با Unity: اگر به دنیای بازی‌سازی علاقه دارید.
  • توسعه‌دهنده ابری (Azure/AWS): برای کار با سرویس‌های ابری و معماری‌های Serverless.
  • تخصص در داده (Data Science / Machine Learning): با استفاده از ML.NET.

هر یک از این مسیرها، مباحث و ابزارهای خاص خود را دارد که می‌توانید به طور عمیق‌تر در آنها متخصص شوید.

۶. اهمیت مهارت‌های نرم (Soft Skills)

در کنار مهارت‌های فنی، مهارت‌های نرم نیز برای یک برنامه‌نویس موفق حیاتی هستند:

  • حل مسئله (Problem Solving): توانایی تجزیه مسائل پیچیده به بخش‌های کوچک‌تر و یافتن راه‌حل‌های کارآمد.
  • اشکال‌زدایی (Debugging): هنر یافتن و رفع خطاها در کد.
  • تفکر الگوریتمی: توانایی طراحی گام به گام راه‌حل‌ها.
  • ارتباطات: توانایی توضیح ایده‌های پیچیده به همکاران و غیربرنامه‌نویسان.
  • کار تیمی: توانایی همکاری موثر با دیگران در پروژه‌ها.

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

موفق باشید!

“تسلط به برنامه‌نویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT”

قیمت اصلی 2.290.000 ریال بود.قیمت فعلی 1.590.000 ریال است.

"تسلط به برنامه‌نویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT"

"با شرکت در این دوره جامع و کاربردی، به راحتی مهارت‌های برنامه‌نویسی پایتون را از سطح مبتدی تا پیشرفته با کمک هوش مصنوعی ChatGPT بیاموزید. این دوره، با بیش از 6 ساعت محتوای آموزشی، شما را قادر می‌سازد تا به سرعت الگوریتم‌های پیچیده را درک کرده و اپلیکیشن‌های هوشمند ایجاد کنید. مناسب برای تمامی سطوح با زیرنویس فارسی حرفه‌ای و امکان دانلود و تماشای آنلاین."

ویژگی‌های کلیدی:

بدون نیاز به تجربه قبلی برنامه‌نویسی

زیرنویس فارسی با ترجمه حرفه‌ای

۳۰ ٪ تخفیف ویژه برای دانشجویان و دانش آموزان