← بازگشت

سوالات مصاحبه C# و پاسخ‌ها

سوالات پایه C#

۱. تفاوت C# با C چیست؟

پاسخ:

C یک زبان برنامه‌نویسی رویه‌ای (Procedural) است، در حالی که C# یک زبان شیءگرا (Object-Oriented) است. تفاوت اصلی و مهم این دو زبان در این است که C# از قابلیت جمع‌آوری خودکار زباله (Automatic Garbage Collection) توسط Common Language Runtime (CLR) پشتیبانی می‌کند، در حالی که C این قابلیت را ندارد.

C# برای اجرا به فریم‌ورک .NET نیاز دارد، در صورتی که C یک زبان مستقل از پلتفرم است. C# همچنین دارای ویژگی‌هایی مانند مدیریت حافظه امن‌تر، پشتیبانی از Generics، LINQ و Async/Await است که در C وجود ندارند.

مثال:

در C#، نیازی به مدیریت دستی حافظه برای آبجکت‌ها نیست؛ CLR به صورت خودکار حافظه اشغال شده توسط آبجکت‌های غیرقابل دسترس را آزاد می‌کند. در مقابل، در C برنامه‌نویس باید به صورت دستی حافظه را با توابعی مانند malloc و free مدیریت کند.

// C# - Garbage Collection خودکار
class MyClass
{
    public MyClass() { Console.WriteLine("MyClass Created"); }
    ~MyClass() { Console.WriteLine("MyClass Finalized"); } // فراخوانی توسط GC
}

// در متد Main یا هر جای دیگر
MyClass obj = new MyClass();
// پس از اتمام استفاده از obj، CLR به صورت خودکار حافظه را مدیریت می‌کند.
obj = null; // آبجکت برای GC واجد شرایط می‌شود
GC.Collect(); // فراخوانی دستی GC (فقط برای تست، در عمل توصیه نمی‌شود)
// C - مدیریت دستی حافظه
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int *arr;
    arr = (int *)malloc(5 * sizeof(int)); // تخصیص حافظه
    if (arr == NULL)
    {
        printf("Memory allocation failed\n");
        return 1;
    }
    // استفاده از arr
    free(arr); // آزاد کردن حافظه
    return 0;
}

۲. تفاوت بین IEnumerable و IQueryable در C# چیست؟ چه زمانی از هر کدام استفاده می‌کنید؟

پاسخ:

IEnumerable برای پرس‌وجو در مجموعه‌های درون حافظه (in-memory collections) استفاده می‌شود، در حالی که IQueryable برای پرس‌وجو در منابع داده خارجی مانند پایگاه‌های داده کاربرد دارد.

IQueryable به شما امکان می‌دهد تا پرس‌وجوهای پیچیده‌تری را در سمت سرور بنویسید و اجرا کنید، زیرا می‌تواند عبارت‌های پرس‌وجو را به زبان SQL یا سایر زبان‌های پرس‌وجو ترجمه کند و تنها داده‌های مورد نیاز را از پایگاه داده واکشی کند. این باعث بهبود عملکرد و کاهش مصرف حافظه می‌شود.

مثال:

فرض کنید لیستی از کاربران در حافظه دارید و می‌خواهید کاربران فعال را فیلتر کنید:

// استفاده از IEnumerable
List<User> users = GetUsersFromMemory(); // فرض کنید این لیست از جایی پر شده است
IEnumerable<User> activeUsers = users.Where(u => u.IsActive); // فیلتر در حافظه

حال فرض کنید می‌خواهید کاربران فعال را از یک پایگاه داده واکشی کنید:

// استفاده از IQueryable با Entity Framework Core
public IQueryable<User> GetActiveUsersFromDatabase(DbContext context)
{
    // این پرس‌وجو به SQL ترجمه شده و در پایگاه داده اجرا می‌شود
    return context.Users.Where(u => u.IsActive);
}
نکته: در مثال IEnumerable، تمام کاربران ابتدا از حافظه واکشی می‌شوند و سپس فیلتر اعمال می‌شود. اما در مثال IQueryable، فیلتر Where به یک عبارت SQL ترجمه می‌شود و تنها کاربران فعال از پایگاه داده واکشی می‌شوند، که کارایی بالاتری دارد.

۳. تفاوت‌های بین async/await و Task.Run در C# هنگام کار با کد ناهمزمان (asynchronous) چیست؟

پاسخ:

async/await برای ایجاد متدهای ناهمزمان استفاده می‌شود که می‌توانند بدون مسدود کردن ترد اصلی (main thread) منتظر بمانند. این برای عملیات I/O-bound (مانند دسترسی به شبکه یا پایگاه داده) که نیازی به مصرف CPU ندارند، بسیار مناسب است.

Task.Run برای اجرای یک delegate یا عبارت lambda بر روی یک ترد از ThreadPool به صورت ناهمزمان استفاده می‌شود. این ابزار برای عملیات CPU-bound (مانند محاسبات سنگین) که ممکن است ترد اصلی را مسدود کنند، مفید است.

مثال:
// استفاده از async/await برای عملیات I/O-bound
public async Task<string> DownloadContentAsync(string url)
{
    using (HttpClient client = new HttpClient())
    {
        // این عملیات I/O-bound است و ترد اصلی را مسدود نمی‌کند
        string content = await client.GetStringAsync(url);
        return content;
    }
}
// استفاده از Task.Run برای عملیات CPU-bound
public async Task<long> CalculateFactorialAsync(int number)
{
    // این عملیات CPU-bound است و با Task.Run به ترد دیگری منتقل می‌شود
    return await Task.Run(() =>
    {
        long result = 1;
        for (int i = 1; i <= number; i++)
        {
            result *= i;
        }
        return result;
    });
}
توضیح: در DownloadContentAsync، await به سیستم اجازه می‌دهد تا در حین دانلود، ترد اصلی را آزاد کند و به کارهای دیگر بپردازد. در CalculateFactorialAsync، Task.Run تضمین می‌کند که محاسبه سنگین فاکتوریل بر روی یک ترد پس‌زمینه اجرا شود و ترد اصلی آزاد بماند تا UI پاسخگو باشد.

۴. روش‌های مختلف به اشتراک‌گذاری داده بین تسک‌ها (tasks) در C# را توضیح دهید.

پاسخ:

داده‌ها را می‌توان با استفاده از ساختارهای داده‌ای ایمن برای ترد (thread-safe data structures) مانند ConcurrentDictionary و ConcurrentQueue یا ساختارهای همگام‌سازی (synchronization constructs) مانند lock، Monitor و Semaphore بین تسک‌ها به اشتراک گذاشت.

انتخاب روش مناسب بستگی به نوع داده، نیاز به همگام‌سازی و پیچیدگی سناریو دارد.

مثال:

۱. استفاده از lock:

private static readonly object _lock = new object();
private static int _counter = 0;

public void IncrementCounter()
{
    lock (_lock)
    {
        _counter++;
    }
}

۲. استفاده از ConcurrentBag (برای مجموعه‌هایی که ترتیب مهم نیست):

using System.Collections.Concurrent;

private static ConcurrentBag<int> _data = new ConcurrentBag<int>();

public void AddData(int item)
{
    _data.Add(item);
}

۳. استفاده از SemaphoreSlim (برای محدود کردن دسترسی به منابع):

private static SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); // حداکثر 1 ترد همزمان

public async Task AccessResourceAsync()
{
    await _semaphore.WaitAsync();
    try
    {
        // دسترسی به منبع مشترک
        Console.WriteLine("Resource accessed");
    }
    finally
    {
        _semaphore.Release();
    }
}

۵. چگونه یک Middleware سفارشی برای مدیریت استثناها (exception handling) در ASP.NET Core پیاده‌سازی می‌کنید؟

پاسخ:

برای پیاده‌سازی یک Middleware سفارشی برای مدیریت استثناها در ASP.NET Core، مراحل زیر را دنبال می‌کنید:

  1. ایجاد کلاس Middleware: یک کلاس جدید ایجاد کنید که شامل منطق مدیریت استثنا باشد. این کلاس باید یک سازنده (constructor) با پارامتر RequestDelegate next و یک متد InvokeAsync (یا Invoke) داشته باشد.
  2. پیاده‌سازی منطق مدیریت استثنا: در متد InvokeAsync، از یک بلوک try-catch برای گرفتن استثناها استفاده کنید. در بلوک catch، می‌توانید استثنا را لاگ کنید و یک پاسخ مناسب (مانند یک صفحه خطا یا JSON با جزئیات خطا) به کلاینت برگردانید.
  3. افزودن Middleware به Pipeline درخواست: از متد app.UseMiddleware<YourCustomExceptionMiddleware>() در کلاس Startup (یا Program.cs در .NET 6 به بالا) برای افزودن Middleware به pipeline درخواست استفاده کنید.
مثال:
// 1. ایجاد کلاس Middleware
public class CustomExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<CustomExceptionMiddleware> _logger;

    public CustomExceptionMiddleware(RequestDelegate next, ILogger<CustomExceptionMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception ex)
        {
            _logger.LogError($"Something went wrong: {ex}");
            httpContext.Response.ContentType = "application/json";
            httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

            await httpContext.Response.WriteAsync(new ErrorDetails()
            {
                StatusCode = httpContext.Response.StatusCode,
                Message = "Internal Server Error from the custom middleware."
            }.ToString());
        }
    }
}
// کلاس کمکی برای جزئیات خطا
public class ErrorDetails
{
    public int StatusCode { get; set; }
    public string Message { get; set; }

    public override string ToString()
    {
        return JsonSerializer.Serialize(this);
    }
}
نکته: این Middleware به شما امکان می‌دهد تا مدیریت خطای متمرکز و سفارشی‌سازی شده‌ای برای برنامه ASP.NET Core خود داشته باشید.

۶. چگونه یک Attribute سفارشی در C# پیاده‌سازی می‌کنید؟ مثالی از نحوه استفاده از آن برای تزئین یک کلاس ارائه دهید.

پاسخ:

برای پیاده‌سازی یک Attribute سفارشی در C#، یک کلاس ایجاد می‌کنید که از کلاس پایه Attribute مشتق شده باشد. می‌توانید ویژگی‌ها (properties) یا فیلدهایی را برای ذخیره داده‌های مرتبط با Attribute اضافه کنید.

برای استفاده از Attribute، آن را با استفاده از سینتکس براکت مربعی ([]) به کلاس‌ها یا اعضا اعمال می‌کنید.

مثال:

فرض کنید می‌خواهید یک Attribute برای نشانه‌گذاری کلاس‌هایی ایجاد کنید که نیاز به لاگ‌برداری خاصی دارند:

using System;

// 1. پیاده‌سازی Attribute سفارشی
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class LoggableAttribute : Attribute
{
    public string Category { get; set; }

    public LoggableAttribute(string category = "General")
    {
        Category = category;
    }
}
// 2. استفاده از Attribute برای تزئین یک کلاس
[Loggable(Category = "DataAccess")]
public class UserRepository
{
    public void GetUserById(int id)
    {
        Console.WriteLine($"Getting user with ID: {id}");
    }

    [Loggable(Category = "Performance")]
    public void SaveUser(User user)
    {
        Console.WriteLine($"Saving user: {user.Name}");
    }
}
// مثالی از نحوه خواندن Attribute در زمان اجرا (Reflection)
public class AttributeReader
{
    public static void ReadAttributes()
    {
        Type type = typeof(UserRepository);
        LoggableAttribute classAttribute = (LoggableAttribute)Attribute.GetCustomAttribute(type, typeof(LoggableAttribute));

        if (classAttribute != null)
        {
            Console.WriteLine($"UserRepository is Loggable. Category: {classAttribute.Category}");
        }

        // خواندن Attribute از متد
        var methodInfo = type.GetMethod("SaveUser");
        LoggableAttribute methodAttribute = (LoggableAttribute)Attribute.GetCustomAttribute(methodInfo, typeof(LoggableAttribute));

        if (methodAttribute != null)
        {
            Console.WriteLine($"SaveUser method is Loggable. Category: {methodAttribute.Category}");
        }
    }
}
کاربرد: این Attribute سفارشی به شما امکان می‌دهد تا متادیتای اضافی را به کد خود اضافه کنید که می‌تواند در زمان اجرا با استفاده از Reflection خوانده شود و برای اهداف مختلفی مانند اعتبارسنجی، لاگ‌برداری، یا پیکربندی استفاده شود.

۷. تفاوت‌های بین Covariance و Contravariance در C# برای Delegateها و Interfaceها را توضیح دهید.

پاسخ:

Covariance و Contravariance مفاهیمی در C# هستند که به شما امکان می‌دهند تا سازگاری نوع (type compatibility) را در زمان کامپایل برای Delegateها و Interfaceها انعطاف‌پذیرتر کنید. این مفاهیم به شما اجازه می‌دهند تا از انواع مشتق شده (derived types) یا انواع پایه (base types) در جاهایی که انتظار می‌رود، استفاده کنید.

مثال Covariance:
// Covariance در Interface
public interface IReadOnlyList<out T> // 'out' نشان‌دهنده Covariance است
{
    T GetItem(int index);
}

public class Animal { }
public class Dog : Animal { }

public class DogList : IReadOnlyList<Dog>
{
    private Dog[] dogs = { new Dog(), new Dog() };
    public Dog GetItem(int index) => dogs[index];
}

public static void TestCovariance()
{
    IReadOnlyList<Dog> dogList = new DogList();
    IReadOnlyList<Animal> animalList = dogList; // Covariance: IReadOnlyList<Dog> به IReadOnlyList<Animal> قابل انتساب است
    Animal animal = animalList.GetItem(0);
    Console.WriteLine("Covariance Test Passed");
}
مثال Contravariance:
// Contravariance در Delegate
public delegate void Action<in T>(T arg); // 'in' نشان‌دهنده Contravariance است

public class Animal { }
public class Dog : Animal { }

public static void ProcessAnimal(Animal animal)
{
    Console.WriteLine($"Processing Animal: {animal.GetType().Name}");
}

public static void TestContravariance()
{
    Action<Animal> animalAction = ProcessAnimal;
    Action<Dog> dogAction = animalAction; // Contravariance: Action<Animal> به Action<Dog> قابل انتساب است
    dogAction(new Dog());
    Console.WriteLine("Contravariance Test Passed");
}
اهمیت: درک این مفاهیم برای نوشتن کدهای انعطاف‌پذیرتر و قابل استفاده مجدد در سناریوهای پیشرفته‌تر C#، به ویژه هنگام کار با Generics و LINQ، بسیار مهم است.

۸. Serialization چیست؟

پاسخ:

Serialization فرآیند تبدیل یک شیء (Object) به یک جریان از بایت‌ها (stream of bytes) است تا بتوان آن را ذخیره کرد (مثلاً در یک فایل) یا از طریق شبکه منتقل کرد. این فرآیند امکان حفظ وضعیت یک شیء را فراهم می‌کند تا بتوان آن را بعداً بازسازی کرد (Deserialization).

Serialization برای حفظ نسخه اصلی کد و بازیابی آن بعداً مفید است.

مثال:

فرض کنید یک کلاس Person دارید و می‌خواهید یک شیء از این کلاس را در یک فایل ذخیره کنید:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
public class SerializationExample
{
    public static void SerializePerson(Person person, string filePath)
    {
        using (FileStream stream = new FileStream(filePath, FileMode.Create))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, person);
            Console.WriteLine($"Person object serialized to {filePath}");
        }
    }

    public static Person DeserializePerson(string filePath)
    {
        using (FileStream stream = new FileStream(filePath, FileMode.Open))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            Person person = (Person)formatter.Deserialize(stream);
            Console.WriteLine($"Person object deserialized from {filePath}");
            return person;
        }
    }
}
// نحوه استفاده:
// Person p1 = new Person { Name = "Ali", Age = 30 };
// SerializationExample.SerializePerson(p1, "person.dat");
// Person p2 = SerializationExample.DeserializePerson("person.dat");
// Console.WriteLine($"Deserialized Person: {p2.Name}, {p2.Age}");

۹. تفاوت بین Continue و Break در C# چیست؟

پاسخ:

مثال:
// مثال Continue
for (int i = 1; i <= 10; i++)
{
    if (i % 2 == 0) // اگر عدد زوج باشد
    {
        continue; // به تکرار بعدی برو
    }
    Console.WriteLine(i); // فقط اعداد فرد چاپ می‌شوند
}
// خروجی: 1, 3, 5, 7, 9
// مثال Break
for (int i = 1; i <= 10; i++)
{
    if (i == 5)
    {
        break; // حلقه را کاملاً متوقف کن
    }
    Console.WriteLine(i);
}
// خروجی: 1, 2, 3, 4
خلاصه: Continue فقط تکرار فعلی را رد می‌کند و به تکرار بعدی می‌رود، در حالی که Break کل حلقه را متوقف می‌کند.

۱۰. تفاوت بین String و StringBuilder در C# چیست؟

پاسخ:

String در C# یک نوع داده غیرقابل تغییر (Immutable) است، به این معنی که هر بار که عملیاتی روی یک رشته انجام می‌دهید، یک شیء جدید در حافظه ایجاد می‌شود. این موضوع در صورت انجام عملیات متعدد روی رشته‌ها می‌تواند باعث مصرف زیاد حافظه و کاهش عملکرد شود.

StringBuilder یک کلاس قابل تغییر (Mutable) است که برای ساخت و دستکاری رشته‌ها بهینه شده است. این کلاس از یک بافر داخلی استفاده می‌کند که می‌تواند بدون ایجاد اشیاء جدید، محتوای رشته را تغییر دهد.

مثال:
// استفاده از String (ناکارآمد برای عملیات متعدد)
string result = "";
for (int i = 0; i < 1000; i++)
{
    result += "Hello "; // هر بار یک شیء جدید ایجاد می‌شود
}
// این کد 1000 شیء String در حافظه ایجاد می‌کند
// استفاده از StringBuilder (کارآمد برای عملیات متعدد)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
    sb.Append("Hello "); // فقط محتوای بافر داخلی تغییر می‌کند
}
string result = sb.ToString(); // تبدیل نهایی به String
توصیه: از String برای عملیات ساده و محدود استفاده کنید. از StringBuilder زمانی استفاده کنید که نیاز به انجام عملیات متعدد روی رشته‌ها دارید، مخصوصاً در حلقه‌ها یا عملیات پیچیده.

۸. Serialization چیست؟

پاسخ:

Serialization فرآیند تبدیل یک شیء (Object) به یک جریان از بایت‌ها (stream of bytes) است تا بتوان آن را ذخیره کرد (مثلاً در یک فایل) یا از طریق شبکه منتقل کرد. این فرآیند امکان حفظ وضعیت یک شیء را فراهم می‌کند تا بتوان آن را بعداً بازسازی کرد (Deserialization). Serialization برای حفظ نسخه اصلی کد و بازیابی آن بعداً مفید است.

مثال:

فرض کنید یک کلاس Person دارید و می‌خواهید یک شیء از این کلاس را در یک فایل ذخیره کنید:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class SerializationExample
{
    public static void SerializePerson(Person person, string filePath)
    {
        using (FileStream stream = new FileStream(filePath, FileMode.Create))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, person);
            Console.WriteLine($"Person object serialized to {filePath}");
        }
    }

    public static Person DeserializePerson(string filePath)
    {
        using (FileStream stream = new FileStream(filePath, FileMode.Open))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            Person person = (Person)formatter.Deserialize(stream);
            Console.WriteLine($"Person object deserialized from {filePath}");
            return person;
        }
    }
}
نکته: در .NET Core و .NET 5+، BinaryFormatter به دلیل مسائل امنیتی منسوخ شده است. بهتر است از System.Text.Json یا Newtonsoft.Json برای JSON serialization استفاده کنید.

۹. تفاوت بین Continue و Break در C# چیست؟

پاسخ:

مثال:
public class LoopControlExample
{
    public static void DemonstrateBreakAndContinue()
    {
        Console.WriteLine("--- Demonstrate Continue ---");
        for (int i = 0; i < 5; i++)
        {
            if (i == 2)
            {
                Console.WriteLine("Skipping iteration 2");
                continue; // پرش از این تکرار
            }
            Console.WriteLine($"Current value (Continue): {i}");
        }

        Console.WriteLine("\n--- Demonstrate Break ---");
        for (int i = 0; i < 5; i++)
        {
            if (i == 3)
            {
                Console.WriteLine("Breaking loop at iteration 3");
                break; // خروج کامل از حلقه
            }
            Console.WriteLine($"Current value (Break): {i}");
        }
    }
}
خروجی:
--- Demonstrate Continue ---
Current value (Continue): 0
Current value (Continue): 1
Skipping iteration 2
Current value (Continue): 3
Current value (Continue): 4

--- Demonstrate Break ---
Current value (Break): 0
Current value (Break): 1
Current value (Break): 2
Breaking loop at iteration 3

۱۰. تفاوت بین Finalize و finally در C# چیست؟

پاسخ:

مثال:
using System;
using System.IO;

public class ResourceHandler : IDisposable
{
    private FileStream _fileStream;

    public ResourceHandler(string filePath)
    {
        _fileStream = new FileStream(filePath, FileMode.Create);
        Console.WriteLine("ResourceHandler created and file opened.");
    }

    // متد Finalize (نهایی‌کننده)
    ~ResourceHandler()
    {
        Console.WriteLine("Finalize method called.");
        Dispose(false);
    }

    // پیاده‌سازی Dispose برای پاکسازی منابع مدیریت شده و غیرمدیریت شده
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this); // جلوگیری از فراخوانی Finalize توسط GC
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            // پاکسازی منابع مدیریت شده
            if (_fileStream != null)
            {
                _fileStream.Dispose();
                _fileStream = null;
                Console.WriteLine("Managed resources disposed.");
            }
        }
        // پاکسازی منابع غیرمدیریت شده (اگر وجود داشته باشند)
        Console.WriteLine("Unmanaged resources (if any) cleaned up.");
    }
}
// مثال استفاده از بلوک finally
public class FinallyExample
{
    public static void DemonstrateFinally()
    {
        FileStream file = null;
        try
        {
            file = new FileStream("test.txt", FileMode.Create);
            // انجام عملیات روی فایل
            Console.WriteLine("File operations completed.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"An error occurred: {ex.Message}");
        }
        finally
        {
            // این بلوک همیشه اجرا می‌شود
            if (file != null)
            {
                file.Dispose();
                Console.WriteLine("File closed in finally block.");
            }
        }
    }
}
نکته: بهتر است از الگوی using statement یا IDisposable برای مدیریت منابع استفاده کنید تا از پاکسازی قطعی و به موقع منابع اطمینان حاصل کنید، زیرا زمان فراخوانی Finalize غیرقابل پیش‌بینی است.

۱۱. Partial Classes در C# چیست؟

پاسخ:

Partial Classes (کلاس‌های جزئی) قابلیتی در C# هستند که به شما امکان می‌دهند تا تعریف یک کلاس را در چندین فایل مختلف تقسیم کنید. این کلاس‌ها با کلمه کلیدی partial مشخص می‌شوند و در زمان کامپایل، کامپایلر آن‌ها را به یک کلاس واحد تبدیل می‌کند.

این قابلیت به ویژه در سناریوهایی مفید است که کد تولید خودکار (Code Generation) وجود دارد یا زمانی که چندین توسعه‌دهنده روی یک کلاس بزرگ کار می‌کنند.

مثال:

فرض کنید یک کلاس Employee دارید که در دو فایل مختلف تعریف شده است:

// فایل Employee.Basic.cs
public partial class Employee
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public string GetFullName()
    {
        return $"{FirstName} {LastName}";
    }
}
// فایل Employee.Contact.cs
public partial class Employee
{
    public string Email { get; set; }
    public string PhoneNumber { get; set; }

    public void DisplayContactInfo()
    {
        Console.WriteLine($"Email: {Email}, Phone: {PhoneNumber}");
    }
}
نکته: در زمان کامپایل، این دو بخش به یک کلاس Employee واحد تبدیل می‌شوند که هم ویژگی‌های Id, FirstName, LastName و متد GetFullName را دارد و هم ویژگی‌های Email, PhoneNumber و متد DisplayContactInfo را. تمام بخش‌های partial باید در یک namespace و assembly قرار گیرند.

۱۲. تفاوت بین Method Overriding و Method Overloading چیست؟

پاسخ:

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

Method Overriding (بازنویسی متد):

مثال Overloading:
public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public double Add(double a, double b)
    {
        return a + b;
    }

    public int Add(int a, int b, int c)
    {
        return a + b + c;
    }
}
مثال Overriding:
public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Animal makes a sound");
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Dog barks");
    }
}

public class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Cat meows");
    }
}
خلاصه تفاوت‌ها:

۱۳. Constructor چیست و انواع آن کدامند؟

پاسخ:

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

انواع Constructor در C#:
مثال Parameterized Constructor:
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    // سازنده پارامتردار
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

// نحوه استفاده
Person p = new Person("علی", 30);
مثال Static Constructor:
public class AppSettings
{
    public static string ConnectionString { get; private set; }

    // سازنده استاتیک - فقط یک بار فراخوانی می‌شود
    static AppSettings()
    {
        ConnectionString = "Data Source=.;Initial Catalog=MyDB;Integrated Security=True";
        Console.WriteLine("Static constructor called.");
    }
}
مثال Singleton Pattern با Private Constructor:
public class Singleton
{
    private static Singleton _instance;
    private static readonly object _lock = new object();

    // سازنده خصوصی
    private Singleton()
    {
        Console.WriteLine("Singleton instance created.");
    }

    public static Singleton GetInstance()
    {
        if (_instance == null)
        {
            lock (_lock)
            {
                if (_instance == null)
                {
                    _instance = new Singleton();
                }
            }
        }
        return _instance;
    }
}

۱۴. Destructor در C# چیست؟

پاسخ:

Destructor (مخرب) یک متد ویژه در C# است که برای انجام عملیات پاکسازی نهایی بر روی منابع غیرمدیریت شده (unmanaged resources) قبل از اینکه Garbage Collector (GC) حافظه اشغال شده توسط یک شیء را آزاد کند، استفاده می‌شود. مخرب‌ها به صورت خودکار توسط GC فراخوانی می‌شوند و نمی‌توان آن‌ها را به صورت دستی فراخوانی کرد.

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

نکات مهم:
مثال:
using System;
using System.IO;

public class ResourceHandler : IDisposable
{
    private FileStream _fileStream;
    private bool _disposed = false;

    public ResourceHandler(string filePath)
    {
        _fileStream = new FileStream(filePath, FileMode.Create);
        Console.WriteLine("ResourceHandler created and file opened.");
    }

    // متد Destructor (مخرب)
    ~ResourceHandler()
    {
        Console.WriteLine("Destructor called.");
        Dispose(false);
    }

    // پیاده‌سازی IDisposable
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this); // جلوگیری از فراخوانی مخرب توسط GC
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // پاکسازی منابع مدیریت شده
                if (_fileStream != null)
                {
                    _fileStream.Dispose();
                    _fileStream = null;
                    Console.WriteLine("Managed resources disposed.");
                }
            }
            // پاکسازی منابع غیرمدیریت شده
            Console.WriteLine("Unmanaged resources cleaned up.");
            _disposed = true;
        }
    }
}
استفاده بهینه با using statement:
// استفاده از using برای پاکسازی خودکار
using (var handler = new ResourceHandler("test.txt"))
{
    // کار با فایل
    Console.WriteLine("Working with file...");
} // در اینجا Dispose() خودکار فراخوانی می‌شود

۱۵. تفاوت بین Static و Instance Members چیست؟

پاسخ:

Static Members (اعضای استاتیک) به کلاس تعلق دارند، نه به یک شیء خاص از آن کلاس. این اعضا در تمام اشیاء کلاس مشترک هستند و بدون نیاز به ایجاد شیء از کلاس قابل دسترسی هستند. در مقابل، Instance Members (اعضای نمونه) به هر شیء خاص از کلاس تعلق دارند و برای دسترسی به آن‌ها باید ابتدا یک شیء از کلاس ایجاد کرد.

تفاوت‌های کلیدی:
مثال:
public class Counter
{
    // Static member - مشترک بین تمام اشیاء
    public static int StaticCount = 0;
    
    // Instance member - مختص هر شیء
    public int InstanceCount = 0;

    public Counter()
    {
        StaticCount++;    // برای تمام اشیاء افزایش می‌یابد
        InstanceCount++;  // فقط برای این شیء افزایش می‌یابد
    }

    public static void DisplayStaticCount()
    {
        Console.WriteLine($"Static Count: {StaticCount}");
        // نمی‌توان به Instance members دسترسی داشت
        // Console.WriteLine($"Instance Count: {InstanceCount}"); // خطا!
    }

    public void DisplayInstanceCount()
    {
        Console.WriteLine($"Instance Count: {InstanceCount}");
        Console.WriteLine($"Static Count: {StaticCount}"); // دسترسی به Static member
    }
}

// نحوه استفاده:
Counter c1 = new Counter(); // StaticCount = 1, c1.InstanceCount = 1
Counter c2 = new Counter(); // StaticCount = 2, c2.InstanceCount = 1
Counter.DisplayStaticCount(); // خروجی: Static Count: 2

۱۶. تفاوت بین Abstract Classes و Interfaces چیست؟

پاسخ:

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

تفاوت‌های اصلی:
مثال Abstract Class:
public abstract class Animal
{
    // فیلد عادی
    protected string name;

    // Constructor
    public Animal(string name)
    {
        this.name = name;
    }

    // متد عادی با پیاده‌سازی
    public void Sleep()
    {
        Console.WriteLine($"{name} is sleeping.");
    }

    // متد انتزاعی - باید در کلاس مشتق پیاده‌سازی شود
    public abstract void MakeSound();
}

public class Dog : Animal
{
    public Dog(string name) : base(name) { }

    public override void MakeSound()
    {
        Console.WriteLine($"{name} barks: Woof!");
    }
}
مثال Interface:
public interface IFlyable
{
    void Fly();
    int MaxAltitude { get; set; }
}

public interface ISwimmable
{
    void Swim();
}

// یک کلاس می‌تواند چندین Interface پیاده‌سازی کند
public class Duck : IFlyable, ISwimmable
{
    public int MaxAltitude { get; set; }

    public void Fly()
    {
        Console.WriteLine("Duck is flying.");
    }

    public void Swim()
    {
        Console.WriteLine("Duck is swimming.");
    }
}

۱۷. Virtual Methods در C# چیست؟

پاسخ:

Virtual Methods (متدهای مجازی) متدهایی هستند که در کلاس پایه با کلمه کلیدی virtual تعریف می‌شوند و امکان بازنویسی (Override) در کلاس‌های مشتق شده را فراهم می‌کنند. این متدها پیاده‌سازی پیش‌فرض دارند اما کلاس‌های مشتق شده می‌توانند رفتار آن‌ها را تغییر دهند. در زمان اجرا، بر اساس نوع واقعی شیء تصمیم گرفته می‌شود که کدام پیاده‌سازی فراخوانی شود.

ویژگی‌های Virtual Methods:
مثال:
public class Shape
{
    // Virtual method با پیاده‌سازی پیش‌فرض
    public virtual double CalculateArea()
    {
        Console.WriteLine("Calculating area for generic shape");
        return 0;
    }

    // Virtual method دیگر
    public virtual void Draw()
    {
        Console.WriteLine("Drawing a generic shape");
    }
}

public class Circle : Shape
{
    private double radius;

    public Circle(double radius)
    {
        this.radius = radius;
    }

    // Override کردن virtual method
    public override double CalculateArea()
    {
        Console.WriteLine("Calculating area for circle");
        return Math.PI * radius * radius;
    }

    // این کلاس Draw را override نکرده، پس پیاده‌سازی پایه استفاده می‌شود
}

public class Rectangle : Shape
{
    private double width, height;

    public Rectangle(double width, double height)
    {
        this.width = width;
        this.height = height;
    }

    public override double CalculateArea()
    {
        Console.WriteLine("Calculating area for rectangle");
        return width * height;
    }

    public override void Draw()
    {
        Console.WriteLine("Drawing a rectangle");
    }
}
استفاده و Runtime Polymorphism:
public static void DemonstrateVirtualMethods()
{
    Shape[] shapes = {
        new Circle(5),
        new Rectangle(4, 6),
        new Shape()
    };

    foreach (Shape shape in shapes)
    {
        // در زمان اجرا تصمیم گرفته می‌شود کدام پیاده‌سازی فراخوانی شود
        double area = shape.CalculateArea();
        Console.WriteLine($"Area: {area}");
        shape.Draw();
        Console.WriteLine("---");
    }
}
نکته: اگر متدی در کلاس پایه virtual نباشد، کلاس مشتق شده می‌تواند از کلمه کلیدی new برای پنهان کردن (hiding) متد استفاده کند، اما این Method Hiding است نه Method Overriding و Polymorphism کار نمی‌کند.

۱۸. Sealed Classes در C# چیست؟

پاسخ:

Sealed Classes (کلاس‌های مهر و موم شده) کلاس‌هایی هستند که با کلمه کلیدی sealed مشخص می‌شوند و امکان ارث‌بری از آن‌ها وجود ندارد. این کلاس‌ها برای جلوگیری از تغییر رفتار اصلی کلاس و بهبود عملکرد (Performance) استفاده می‌شوند، زیرا کامپایلر می‌تواند بهینه‌سازی‌های بیشتری روی آن‌ها انجام دهد.

دلایل استفاده از Sealed Classes:
مثال:
// کلاس sealed - نمی‌توان از آن ارث‌بری کرد
public sealed class MathUtility
{
    public static double CalculateCircleArea(double radius)
    {
        return Math.PI * radius * radius;
    }

    public static double CalculateRectangleArea(double width, double height)
    {
        return width * height;
    }
}

// این کد خطا می‌دهد چون نمی‌توان از sealed class ارث‌بری کرد
// public class ExtendedMathUtility : MathUtility // خطای کامپایل!
// {
// }
مثال Sealed Method:
public class BaseClass
{
    public virtual void Method1()
    {
        Console.WriteLine("BaseClass Method1");
    }
}

public class MiddleClass : BaseClass
{
    // Override کردن و sealed کردن متد
    public sealed override void Method1()
    {
        Console.WriteLine("MiddleClass Method1 - Sealed");
    }
}

public class DerivedClass : MiddleClass
{
    // نمی‌توان Method1 را override کرد چون sealed است
    // public override void Method1() // خطای کامپایل!
    // {
    // }
}
نکته: کلاس String در .NET Framework یک مثال از کلاس sealed است. این تضمین می‌کند که رفتار اصلی String هرگز تغییر نکند و عملکرد آن قابل پیش‌بینی باشد.

۱۹. Enum چیست؟

پاسخ:

Enum (Enumeration یا شمارش) یک نوع داده (Value Type) است که شامل مجموعه‌ای از ثابت‌های نام‌گذاری شده (named constants) است. این ثابت‌ها به صورت پیش‌فرض از نوع int هستند و از 0 شروع می‌شوند، اما می‌توان نوع زیرین و مقادیر آن‌ها را تغییر داد. Enumها برای تعریف مجموعه‌ای از مقادیر مرتبط و خوانا استفاده می‌شوند که در طول برنامه تغییر نمی‌کنند.

دلایل استفاده از Enum:
مثال:
public enum DayOfWeek
{
    Sunday,    // 0 به صورت پیش‌فرض
    Monday,    // 1
    Tuesday,   // 2
    Wednesday, // 3
    Thursday,  // 4
    Friday,    // 5
    Saturday   // 6
}

public enum StatusCode : int // تعریف نوع زیرین به صورت int
{
    Success = 200,
    BadRequest = 400,
    Unauthorized = 401,
    NotFound = 404,
    InternalServerError = 500
}

public class EnumExample
{
    public static void DemonstrateEnums()
    {
        DayOfWeek today = DayOfWeek.Wednesday;
        Console.WriteLine($"Today is {today} ({(int)today})");

        StatusCode responseStatus = StatusCode.InternalServerError;
        Console.WriteLine($"Response Status: {responseStatus} ({(int)responseStatus})");

        if (today == DayOfWeek.Friday)
        {
            Console.WriteLine("It's Friday! Time for weekend.");
        }
    }
}
Flags Enum برای مقادیر ترکیبی:
[Flags]
public enum FilePermissions
{
    None = 0,
    Read = 1,
    Write = 2,
    Execute = 4,
    ReadWrite = Read | Write,
    All = Read | Write | Execute
}

// استفاده
FilePermissions permissions = FilePermissions.Read | FilePermissions.Write;
Console.WriteLine($"Permissions: {permissions}"); // خروجی: ReadWrite
Console.WriteLine($"Has Read: {permissions.HasFlag(FilePermissions.Read)}"); // True

۲۰. تفاوت بین const و readonly در C# چیست؟

پاسخ:

هر دو کلمه کلیدی const و readonly برای تعریف فیلدهایی استفاده می‌شوند که مقدار آن‌ها پس از مقداردهی اولیه قابل تغییر نیست، اما تفاوت‌های مهمی در زمان مقداردهی و نحوه عملکرد دارند.

تفاوت‌های اصلی:
مثال:
public class ConstantsAndReadonly
{
    // const - مقداردهی در زمان کامپایل
    public const double PI = 3.14159;
    public const string CompanyName = "MyCompany";

    // readonly - می‌تواند در سازنده مقداردهی شود
    public readonly int MaxValue;
    public readonly DateTime CreationTime;
    
    // static readonly - مقداردهی در زمان اجرا (فقط یک بار)
    public static readonly DateTime StartDate = DateTime.Now;

    public ConstantsAndReadonly(int maxValue)
    {
        MaxValue = maxValue; // مقداردهی readonly در سازنده
        CreationTime = DateTime.Now;
    }

    public void DisplayValues()
    {
        Console.WriteLine($"PI: {PI}");
        Console.WriteLine($"Company: {CompanyName}");
        Console.WriteLine($"MaxValue: {MaxValue}");
        Console.WriteLine($"Creation Time: {CreationTime}");
        Console.WriteLine($"Start Date: {StartDate}");
    }
}
نحوه استفاده:
public static void DemonstrateConstantsAndReadonly()
{
    // دسترسی به const از طریق نام کلاس
    Console.WriteLine($"PI: {ConstantsAndReadonly.PI}");
    
    // ایجاد اشیاء مختلف با مقادیر readonly متفاوت
    ConstantsAndReadonly obj1 = new ConstantsAndReadonly(100);
    ConstantsAndReadonly obj2 = new ConstantsAndReadonly(200);
    
    obj1.DisplayValues();
    obj2.DisplayValues();
    
    // StartDate برای همه شیءها یکسان است
    Console.WriteLine($"Static Start Date: {ConstantsAndReadonly.StartDate}");
}
خلاصه: const برای مقادیر ثابت و شناخته شده در زمان کامپایل (مانند ثابت‌های ریاضی) مناسب است، در حالی که readonly برای مقادیری استفاده می‌شود که ممکن است در زمان اجرا (مثلاً از طریق تنظیمات یا ورودی کاربر) مقداردهی شوند اما پس از آن نباید تغییر کنند.

۲۱. تفاوت بین Stack و Heap در مدیریت حافظه C# چیست؟

پاسخ:

در C#، حافظه به دو بخش اصلی تقسیم می‌شود: Stack (پشته) و Heap (هیپ). این دو بخش نقش‌های متفاوتی در ذخیره‌سازی داده‌ها و مدیریت حافظه دارند.

Stack (پشته):

Heap (هیپ):

مثال:
public class MemoryExample
{
    public void DemonstrateMemory()
    {
        int valueType = 10; // ذخیره شده در Stack
        string referenceType = "Hello"; // "Hello" در Heap، رفرنس به آن در Stack
        MyObject obj = new MyObject(); // MyObject در Heap، رفرنس به آن در Stack

        // وقتی متد به پایان می‌رسد، valueType و رفرنس‌ها از Stack حذف می‌شوند
        // اما اشیاء در Heap تا زمان GC باقی می‌مانند
    }
}

public class MyObject
{
    public int Id { get; set; }
}

۲۲. Value Type و Reference Type در C# چه تفاوتی دارند؟

پاسخ:

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

تفاوت‌های اصلی:
مثال:
public class TypeDifferenceExample
{
    public static void DemonstrateTypes()
    {
        // Value Type Example
        int a = 10; // a در Stack ذخیره می‌شود
        int b = a;  // یک کپی از 10 در b ذخیره می‌شود، b مستقل از a است
        b = 20;
        Console.WriteLine($"Value Type: a = {a}, b = {b}"); // خروجی: a = 10, b = 20

        // Reference Type Example
        MyClass obj1 = new MyClass { Value = 10 }; // obj1 رفرنسی به شیء در Heap است
        MyClass obj2 = obj1; // obj2 نیز به همان شیء در Heap اشاره می‌کند
        obj2.Value = 20;
        Console.WriteLine($"Reference Type: obj1.Value = {obj1.Value}, obj2.Value = {obj2.Value}"); 
        // خروجی: obj1.Value = 20, obj2.Value = 20
    }
}

public class MyClass
{
    public int Value { get; set; }
}

۲۳. Boxing و Unboxing در C# چیست؟

پاسخ:

Boxing و Unboxing فرآیندهایی هستند که امکان تبدیل بین Value Typeها و Reference Typeها را فراهم می‌کنند. این عملیات‌ها می‌توانند سربار عملکردی (Performance Overhead) ایجاد کنند و باید در صورت امکان از آن‌ها اجتناب شود.

Boxing (باکسینگ): فرآیند تبدیل یک Value Type به یک Reference Type (یعنی object). هنگامی که یک Value Type باکس می‌شود، یک شیء جدید در Heap ایجاد می‌شود و مقدار Value Type در آن کپی می‌شود.

Unboxing (آنباکسینگ): فرآیند تبدیل یک Reference Type (که قبلاً از یک Value Type باکس شده است) به همان Value Type اصلی. برای انجام Unboxing، ابتدا باید رفرنس را به صورت صریح به Value Type مورد نظر کست (cast) کنید.

مثال Boxing:
int num = 123;       // Value Type در Stack
object obj = num;    // Boxing: num به object تبدیل می‌شود و در Heap ذخیره می‌گردد
Console.WriteLine($"Num: {num}, Obj: {obj}");
مثال Unboxing:
object obj = 123;    // Boxing (قبلاً انجام شده)
int num = (int)obj;  // Unboxing: obj به int تبدیل می‌شود و مقدار آن از Heap به Stack کپی می‌گردد
Console.WriteLine($"Num: {num}, Obj: {obj}");

// مثال InvalidCastException
// object obj2 = "hello";
// int num2 = (int)obj2; // InvalidCastException در زمان اجرا
چرا باید از Boxing/Unboxing اجتناب کرد؟

۲۴. Generics در C# چیست و چرا مفید هستند؟

پاسخ:

Generics (انواع عمومی) قابلیتی در C# هستند که به شما امکان می‌دهند تا کلاس‌ها، Interfaceها، متدها و Delegateها را با پارامترهای نوع (Type Parameters) تعریف کنید. این پارامترها در زمان کامپایل با انواع داده واقعی جایگزین می‌شوند. Generics به شما اجازه می‌دهند تا کدهای قابل استفاده مجدد، نوع-امن (type-safe) و با عملکرد بالا بنویسید.

چرا Generics مفید هستند؟
مثال کلاس Generic:
// کلاس Generic برای یک جفت مقدار
public class Pair<T1, T2>
{
    public T1 First { get; set; }
    public T2 Second { get; set; }

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

    public void Display()
    {
        Console.WriteLine($"First: {First}, Second: {Second}");
    }
}
مثال متد Generic:
// متد Generic برای چاپ یک لیست
public class GenericMethodExample
{
    public static void PrintList<T>(List<T> list)
    {
        foreach (T item in list)
        {
            Console.WriteLine(item);
        }
    }
}

// استفاده
public static void DemonstrateGenerics()
{
    // استفاده از کلاس Generic با انواع مختلف
    Pair<int, string> intStringPair = new Pair<int, string>(1, "One");
    intStringPair.Display();

    Pair<string, double> stringDoublePair = new Pair<string, double>("Pi", 3.14);
    stringDoublePair.Display();

    // استفاده از متد Generic
    List<int> numbers = new List<int> { 10, 20, 30 };
    GenericMethodExample.PrintList(numbers);
}

۲۵. Extension Methods در C# چیست و چگونه مفید هستند؟

پاسخ:

Extension Methods (متدهای توسعه‌دهنده) قابلیتی در C# هستند که به شما امکان می‌دهند تا متدهای جدیدی را به انواع موجود (Existing Types) اضافه کنید، بدون اینکه نیاز به تغییر کد منبع آن نوع یا ایجاد یک کلاس مشتق شده داشته باشید. این متدها به صورت متدهای Instance فراخوانی می‌شوند، گویی که بخشی از نوع اصلی هستند.

چگونه Extension Methods را تعریف می‌کنیم؟
چرا Extension Methods مفید هستند؟
مثال:
// کلاس static برای تعریف Extension Methods
public static class StringExtensions
{
    // Extension Method برای شمارش کلمات در یک رشته
    public static int WordCount(this string str)
    {
        if (string.IsNullOrWhiteSpace(str))
        {
            return 0;
        }
        return str.Split(new char[] { ' ', '.', '?', '!' }, StringSplitOptions.RemoveEmptyEntries).Length;
    }

    // Extension Method برای معکوس کردن یک رشته
    public static string Reverse(this string str)
    {
        char[] charArray = str.ToCharArray();
        Array.Reverse(charArray);
        return new string(charArray);
    }
}
استفاده:
public static void DemonstrateExtensionMethods()
{
    string sentence = "Hello world! This is a test sentence.";
    int count = sentence.WordCount(); // فراخوانی Extension Method
    Console.WriteLine($"Sentence: \"{sentence}\"\nWord Count: {count}");

    string original = "CSharp";
    string reversed = original.Reverse(); // فراخوانی Extension Method
    Console.WriteLine($"Original: {original}, Reversed: {reversed}");
}
نکته: Extension Methods به طور گسترده در LINQ استفاده می‌شوند، جایی که متدهایی مانند Where(), Select(), OrderBy() به انواع IEnumerable<T> اضافه شده‌اند.

۲۶. تفاوت بین ref و out در C# چیست؟

پاسخ:

ref و out هر دو کلمات کلیدی هستند که برای پاس دادن آرگومان‌ها به متدها به صورت ارجاع (by reference) استفاده می‌شوند، به این معنی که تغییرات ایجاد شده در پارامتر داخل متد، بر روی متغیر اصلی در خارج از متد نیز تأثیر می‌گذارد. با این حال، تفاوت‌های مهمی در زمان مقداردهی و نحوه عملکرد دارند.

تفاوت‌های اصلی:
مثال:
public class RefOutExample
{
    public static void DemonstrateRefOut()
    {
        // مثال ref
        int refValue = 10;
        Console.WriteLine($"Before RefMethod: {refValue}"); // خروجی: 10
        RefMethod(ref refValue);
        Console.WriteLine($"After RefMethod: {refValue}");  // خروجی: 11

        // مثال out
        int outValue; // نیازی به مقداردهی اولیه نیست
        OutMethod(out outValue);
        Console.WriteLine($"After OutMethod: {outValue}"); // خروجی: 5
    }

    public static void RefMethod(ref int value)
    {
        value++; // مقدار value اصلی تغییر می‌کند
    }

    public static void OutMethod(out int value)
    {
        value = 5; // متد باید value را مقداردهی کند
    }
}
مثال کاربردی - TryParse:
public static void DemonstrateTryParse()
{
    string input = "123";
    int result;
    
    // TryParse از out parameter استفاده می‌کند
    if (int.TryParse(input, out result))
    {
        Console.WriteLine($"Parsing successful: {result}");
    }
    else
    {
        Console.WriteLine("Parsing failed");
    }
}

۲۷. Managed Code و Unmanaged Code در .NET چیست؟

پاسخ:

در محیط .NET، کد به دو دسته اصلی تقسیم می‌شود: Managed Code و Unmanaged Code.

Managed Code (کد مدیریت شده):

Unmanaged Code (کد مدیریت نشده):

مثال فراخوانی Unmanaged Code:
using System;
using System.Runtime.InteropServices;

public class CodeTypeExample
{
    // مثال فراخوانی Unmanaged Code (Win32 API) از Managed Code
    [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern int MessageBox(IntPtr hWnd, string lpText, string lpCaption, uint uType);

    public static void DemonstrateCodeTypes()
    {
        // این یک Managed Code است
        Console.WriteLine("This is Managed Code running in .NET.");

        // فراخوانی یک تابع Unmanaged Code
        // MessageBox(IntPtr.Zero, "Hello from Unmanaged Code!", "Unmanaged Call", 0);
    }
}
نکته: درک تفاوت بین این دو نوع کد برای توسعه‌دهندگان .NET مهم است، به خصوص زمانی که نیاز به تعامل با سیستم عامل یا کتابخانه‌های قدیمی‌تر دارند.

۲۸. Object در C# چیست؟

پاسخ:

در C#، Object (شیء) یک نمونه (Instance) از یک کلاس است. کلاس یک طرح اولیه (Blueprint) یا الگو برای ایجاد اشیاء است، در حالی که شیء یک موجودیت واقعی است که بر اساس آن طرح اولیه ساخته شده و در حافظه وجود دارد. هر شیء دارای حالت (State) و رفتار (Behavior) است.

نکات کلیدی:
مثال:
public class Car
{
    public string Model { get; set; }
    public int Year { get; set; }

    public void Start()
    {
        Console.WriteLine($"{Model} ({Year}) started.");
    }
}

public class ObjectExample
{
    public static void DemonstrateObject()
    {
        // ایجاد یک شیء (instance) از کلاس Car
        Car myCar = new Car(); // myCar یک شیء است

        // مقداردهی به حالت شیء
        myCar.Model = "Toyota";
        myCar.Year = 2020;

        // فراخوانی رفتار شیء
        myCar.Start();

        // مثال از object به عنوان نوع پایه همه چیز
        object obj1 = 10; // Boxing int به object
        object obj2 = "Hello"; // string به object
        object obj3 = myCar; // Car object به object

        Console.WriteLine($"obj1 type: {obj1.GetType().Name}, value: {obj1}");
        Console.WriteLine($"obj2 type: {obj2.GetType().Name}, value: {obj2}");
        Console.WriteLine($"obj3 type: {obj3.GetType().Name}");
    }
}

۲۹. Collections در C# چیست؟

پاسخ:

Collections (مجموعه‌ها) کلاس‌ها و رابط‌هایی هستند که برای ذخیره‌سازی و مدیریت گروهی از اشیاء استفاده می‌شوند. آن‌ها جایگزین انعطاف‌پذیرتری برای آرایه‌ها محسوب می‌شوند و امکانات بیشتری مانند اضافه کردن، حذف کردن و جستجو در عناصر را فراهم می‌کنند. Collections در C# به دو دسته اصلی تقسیم می‌شوند: Non-Generic Collections و Generic Collections.

انواع اصلی Collections:
مثال Generic Collections:
using System;
using System.Collections.Generic;

public class CollectionsExample
{
    public static void DemonstrateCollections()
    {
        // List<T> - لیست قابل تغییر
        List<string> names = new List<string>();
        names.Add("علی");
        names.Add("فاطمه");
        names.Add("حسن");
        Console.WriteLine($"Count: {names.Count}");

        // Dictionary<TKey, TValue> - کلید-مقدار
        Dictionary<int, string> students = new Dictionary<int, string>
        {
            {1, "احمد"},
            {2, "زهرا"},
            {3, "محمد"}
        };
        
        Console.WriteLine($"Student 2: {students[2]}");

        // HashSet<T> - مجموعه بدون تکرار
        HashSet<int> uniqueNumbers = new HashSet<int> {1, 2, 3, 2, 1};
        Console.WriteLine($"Unique count: {uniqueNumbers.Count}"); // خروجی: 3
    }
}
مثال LINQ با Collections:
using System.Linq;

public static void DemonstrateLinqWithCollections()
{
    List<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // فیلتر کردن اعداد زوج
    var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();
    Console.WriteLine($"Even numbers: {string.Join(", ", evenNumbers)}");
    
    // تبدیل به مربع
    var squares = numbers.Select(n => n * n).ToList();
    Console.WriteLine($"Squares: {string.Join(", ", squares)}");
}

۳۰. Nullable Types در C# چیست؟

پاسخ:

Nullable Types (انواع قابل تهی) امکان انتساب مقدار null را به Value Typeها فراهم می‌کنند. به طور پیش‌فرض، Value Typeها (مانند int، bool، DateTime) نمی‌توانند مقدار null داشته باشند، اما با استفاده از Nullable Types، می‌توانید این محدودیت را برطرف کنید. این ویژگی به خصوص در کار با پایگاه‌های داده که ممکن است فیلدهای null داشته باشند، بسیار مفید است.

نحوه تعریف Nullable Types:
مثال:
public class NullableExample
{
    public static void DemonstrateNullableTypes()
    {
        // تعریف Nullable Types
        int? nullableInt = null;
        bool? nullableBool = true;
        DateTime? nullableDate = DateTime.Now;

        // بررسی وجود مقدار
        if (nullableInt.HasValue)
        {
            Console.WriteLine($"Value: {nullableInt.Value}");
        }
        else
        {
            Console.WriteLine("nullableInt is null");
        }

        // استفاده از GetValueOrDefault
        Console.WriteLine($"Int value or default: {nullableInt.GetValueOrDefault()}");
        Console.WriteLine($"Int value or custom default: {nullableInt.GetValueOrDefault(100)}");

        // Null Coalescing Operator (??)
        int actualValue = nullableInt ?? 0; // اگر null باشد، 0 استفاده کن
        Console.WriteLine($"Actual value: {actualValue}");
    }
}
مثال کاربردی با پایگاه داده:
public class Person
{
    public string Name { get; set; }
    public int? Age { get; set; } // ممکن است در پایگاه داده null باشد
    public DateTime? BirthDate { get; set; }

    public void DisplayInfo()
    {
        Console.WriteLine($"Name: {Name}");
        Console.WriteLine($"Age: {(Age.HasValue ? Age.Value.ToString() : "Unknown")}");
        Console.WriteLine($"Birth Date: {(BirthDate?.ToString("yyyy-MM-dd") ?? "Unknown")}");
    }
}

// استفاده
Person person = new Person 
{ 
    Name = "علی", 
    Age = null, // سن مشخص نیست
    BirthDate = new DateTime(1990, 5, 15) 
};
person.DisplayInfo();
نکته: از C# 8.0 به بعد، Nullable Reference Types نیز معرفی شده که امکان کنترل null بودن Reference Typeها را نیز فراهم می‌کند و به کاهش NullReferenceException کمک می‌کند.

۳۱. LINQ در C# چیست؟

پاسخ:

LINQ (Language Integrated Query) یک مجموعه ویژگی در C# است که امکان نوشتن پرس‌وجوهای قدرتمند و خوانا را مستقیماً در کد C# فراهم می‌کند. LINQ به شما اجازه می‌دهد تا با استفاده از syntax مشابه SQL، روی انواع مختلف منابع داده (مانند آرایه‌ها، لیست‌ها، XML، پایگاه‌های داده) پرس‌وجو انجام دهید. LINQ دو syntax اصلی دارد: Query Syntax و Method Syntax.

مزایای LINQ:
مثال Query Syntax:
using System;
using System.Linq;
using System.Collections.Generic;

public class LinqExample
{
    public static void DemonstrateQuerySyntax()
    {
        List<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        // Query Syntax
        var evenNumbers = from num in numbers
                         where num % 2 == 0
                         orderby num descending
                         select num;

        Console.WriteLine("Even numbers (Query Syntax):");
        foreach (var num in evenNumbers)
        {
            Console.WriteLine(num);
        }
    }
}
مثال Method Syntax:
public static void DemonstrateMethodSyntax()
{
    List<string> names = new List<string> {"علی", "فاطمه", "حسن", "زهرا", "احمد"};

    // Method Syntax
    var longNames = names
        .Where(name => name.Length > 3)
        .OrderBy(name => name)
        .Select(name => name.ToUpper())
        .ToList();

    Console.WriteLine("Long names (Method Syntax):");
    longNames.ForEach(Console.WriteLine);
}
مثال پیشرفته با اشیاء:
public class Student
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Major { get; set; }
}

public static void DemonstrateComplexLinq()
{
    List<Student> students = new List<Student>
    {
        new Student { Name = "علی", Age = 20, Major = "کامپیوتر" },
        new Student { Name = "فاطمه", Age = 22, Major = "ریاضی" },
        new Student { Name = "حسن", Age = 19, Major = "کامپیوتر" },
        new Student { Name = "زهرا", Age = 21, Major = "فیزیک" }
    };

    // گروه‌بندی بر اساس رشته تحصیلی
    var groupedByMajor = students
        .GroupBy(s => s.Major)
        .Select(g => new { Major = g.Key, Count = g.Count(), Students = g.ToList() });

    foreach (var group in groupedByMajor)
    {
        Console.WriteLine($"Major: {group.Major}, Count: {group.Count}");
    }
}

۳۲. Lambda Expressions در C# چیست؟

پاسخ:

Lambda Expressions (عبارات لامبدا) راهی مختصر برای نوشتن توابع کوچک و بی‌نام (Anonymous Functions) هستند. آن‌ها به طور گسترده در LINQ، Event Handling و هر جایی که نیاز به یک delegate یا expression tree دارید، استفاده می‌شوند. Lambda expressions با استفاده از عملگر => (lambda operator) تعریف می‌شوند که به آن "goes to" نیز گفته می‌شود.

ساختار Lambda Expression:
مثال‌های مختلف Lambda:
using System;
using System.Collections.Generic;
using System.Linq;

public class LambdaExample
{
    public static void DemonstrateLambda()
    {
        List<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        // Lambda با یک پارامتر
        var evenNumbers = numbers.Where(x => x % 2 == 0).ToList();
        Console.WriteLine($"Even numbers: {string.Join(", ", evenNumbers)}");

        // Lambda با چند پارامتر
        var pairs = numbers.Select((value, index) => new { Index = index, Value = value });
        foreach (var pair in pairs.Take(3))
        {
            Console.WriteLine($"Index: {pair.Index}, Value: {pair.Value}");
        }

        // Statement Lambda
        numbers.ForEach(x => 
        {
            if (x % 2 == 0)
                Console.WriteLine($"{x} is even");
            else
                Console.WriteLine($"{x} is odd");
        });
    }
}
مثال با Delegates:
public delegate int MathOperation(int x, int y);

public static void DemonstrateLambdaWithDelegates()
{
    // استفاده از Lambda با Delegate
    MathOperation add = (x, y) => x + y;
    MathOperation multiply = (x, y) => x * y;

    Console.WriteLine($"Add: {add(5, 3)}"); // خروجی: 8
    Console.WriteLine($"Multiply: {multiply(5, 3)}"); // خروجی: 15

    // استفاده از Func<T>
    Func<int, int, int> subtract = (x, y) => x - y;
    Console.WriteLine($"Subtract: {subtract(10, 4)}"); // خروجی: 6

    // استفاده از Action<T>
    Action<string> printMessage = message => Console.WriteLine($"Message: {message}");
    printMessage("Hello Lambda!");
}

۳۳. Delegates در C# چیست؟

پاسخ:

Delegates (نمایندگان) نوع داده‌ای هستند که رفرنس به متدها را نگه می‌دارند. آن‌ها مشابه اشاره‌گرهای تابع (Function Pointers) در زبان‌های دیگر هستند، اما type-safe و object-oriented هستند. Delegates امکان فراخوانی غیرمستقیم متدها، پیاده‌سازی callback functions و event handling را فراهم می‌کنند. چندین متد می‌توانند به یک delegate اختصاص یابند (Multicast Delegates).

انواع Delegates:
مثال تعریف و استفاده از Delegate:
// تعریف یک delegate
public delegate void NotificationDelegate(string message);
public delegate int CalculationDelegate(int x, int y);

public class DelegateExample
{
    public static void EmailNotification(string message)
    {
        Console.WriteLine($"Email: {message}");
    }

    public static void SMSNotification(string message)
    {
        Console.WriteLine($"SMS: {message}");
    }

    public static int Add(int x, int y)
    {
        return x + y;
    }

    public static int Multiply(int x, int y)
    {
        return x * y;
    }

    public static void DemonstrateDelegates()
    {
        // Single-cast delegate
        NotificationDelegate notify = EmailNotification;
        notify("Welcome to our service!"); // خروجی: Email: Welcome to our service!

        // Multicast delegate
        notify += SMSNotification; // اضافه کردن متد دوم
        notify("Your order is ready!"); // هر دو متد فراخوانی می‌شوند

        // Delegate با return value
        CalculationDelegate calc = Add;
        Console.WriteLine($"Addition: {calc(5, 3)}"); // خروجی: 8

        calc = Multiply;
        Console.WriteLine($"Multiplication: {calc(5, 3)}"); // خروجی: 15
    }
}
مثال با Generic Delegates:
public static void DemonstrateGenericDelegates()
{
    // Func<T> - delegate با return value
    Func<int, int, int> mathOperation = (x, y) => x + y;
    Console.WriteLine($"Func result: {mathOperation(10, 5)}");

    // Action<T> - delegate بدون return value
    Action<string> logger = message => Console.WriteLine($"Log: {message}");
    logger("Application started");

    // Predicate<T> - delegate که bool برمی‌گرداند
    Predicate<int> isEven = number => number % 2 == 0;
    Console.WriteLine($"Is 4 even? {isEven(4)}"); // خروجی: True
}

۳۴. Events در C# چیست؟

پاسخ:

Events (رویدادها) مکانیزمی برای اطلاع‌رسانی در C# هستند که به یک کلاس اجازه می‌دهند تا زمانی که اتفاق خاصی رخ می‌دهد، سایر کلاس‌ها را مطلع کند. Events بر پایه Delegates ساخته شده‌اند اما امنیت بیشتری فراهم می‌کنند. آن‌ها از الگوی طراحی Observer Pattern پیروی می‌کنند و coupling کمتری بین اجزای برنامه ایجاد می‌کنند.

ویژگی‌های Events:
مثال تعریف و استفاده از Event:
// تعریف EventArgs سفارشی
public class OrderEventArgs : EventArgs
{
    public string OrderId { get; set; }
    public decimal Amount { get; set; }
    public DateTime OrderDate { get; set; }
}

// کلاس Publisher
public class OrderService
{
    // تعریف event
    public event EventHandler<OrderEventArgs> OrderPlaced;

    // متد محافظت شده برای فعال کردن event
    protected virtual void OnOrderPlaced(OrderEventArgs e)
    {
        OrderPlaced?.Invoke(this, e);
    }

    public void PlaceOrder(string orderId, decimal amount)
    {
        // منطق ثبت سفارش
        Console.WriteLine($"Processing order {orderId} for ${amount}");

        // فعال کردن event
        OnOrderPlaced(new OrderEventArgs 
        { 
            OrderId = orderId, 
            Amount = amount, 
            OrderDate = DateTime.Now 
        });
    }
}
مثال Subscribers:
// کلاس‌های Subscriber
public class EmailService
{
    public void SendOrderConfirmation(object sender, OrderEventArgs e)
    {
        Console.WriteLine($"Email sent for order {e.OrderId} - Amount: ${e.Amount}");
    }
}

public class InventoryService
{
    public void UpdateInventory(object sender, OrderEventArgs e)
    {
        Console.WriteLine($"Inventory updated for order {e.OrderId}");
    }
}

// استفاده
public static void DemonstrateEvents()
{
    OrderService orderService = new OrderService();
    EmailService emailService = new EmailService();
    InventoryService inventoryService = new InventoryService();

    // Subscribe کردن به event
    orderService.OrderPlaced += emailService.SendOrderConfirmation;
    orderService.OrderPlaced += inventoryService.UpdateInventory;

    // فعال کردن event
    orderService.PlaceOrder("ORD-001", 299.99m);

    // Unsubscribe کردن
    orderService.OrderPlaced -= emailService.SendOrderConfirmation;
    
    orderService.PlaceOrder("ORD-002", 150.00m); // فقط inventory update می‌شود
}

۳۵. Exception Handling در C# چیست؟

پاسخ:

Exception Handling (مدیریت استثناها) مکانیزمی در C# است که به شما امکان می‌دهد تا خطاهای زمان اجرا (Runtime Errors) را به صورت کنترل شده مدیریت کنید. این مکانیزم از بلوک‌های try، catch، finally و throw استفاده می‌کند تا برنامه در مواجهه با خطا به صورت غیرمنتظره متوقف نشود و تجربه کاربری بهتری ارائه دهد.

بلوک‌های Exception Handling:
مثال پایه:
public class ExceptionHandlingExample
{
    public static void DemonstrateBasicExceptionHandling()
    {
        try
        {
            Console.Write("Enter a number: ");
            string input = Console.ReadLine();
            int number = int.Parse(input); // ممکن است FormatException ایجاد کند
            
            int result = 100 / number; // ممکن است DivideByZeroException ایجاد کند
            Console.WriteLine($"Result: {result}");
        }
        catch (FormatException ex)
        {
            Console.WriteLine($"Invalid format: {ex.Message}");
        }
        catch (DivideByZeroException ex)
        {
            Console.WriteLine($"Cannot divide by zero: {ex.Message}");
        }
        catch (Exception ex) // Generic exception handler
        {
            Console.WriteLine($"An error occurred: {ex.Message}");
        }
        finally
        {
            Console.WriteLine("Cleanup operations completed.");
        }
    }
}
مثال Custom Exception:
// تعریف استثنای سفارشی
public class InsufficientBalanceException : Exception
{
    public decimal CurrentBalance { get; }
    public decimal RequestedAmount { get; }

    public InsufficientBalanceException(decimal currentBalance, decimal requestedAmount)
        : base($"Insufficient balance. Current: ${currentBalance}, Requested: ${requestedAmount}")
    {
        CurrentBalance = currentBalance;
        RequestedAmount = requestedAmount;
    }
}

public class BankAccount
{
    private decimal balance;

    public BankAccount(decimal initialBalance)
    {
        balance = initialBalance;
    }

    public void Withdraw(decimal amount)
    {
        if (amount > balance)
        {
            throw new InsufficientBalanceException(balance, amount);
        }
        
        balance -= amount;
        Console.WriteLine($"Withdrawn ${amount}. New balance: ${balance}");
    }
}

// استفاده
public static void DemonstrateCustomException()
{
    BankAccount account = new BankAccount(100);
    
    try
    {
        account.Withdraw(150); // این استثنا ایجاد می‌کند
    }
    catch (InsufficientBalanceException ex)
    {
        Console.WriteLine($"Transaction failed: {ex.Message}");
        Console.WriteLine($"Available balance: ${ex.CurrentBalance}");
    }
}
بهترین شیوه‌ها:

۳۶. Async/Await در C# چیست؟

پاسخ:

Async/Await الگوی برنامه‌نویسی ناهمزمان (Asynchronous Programming) در C# است که امکان اجرای عملیات‌های طولانی‌مدت (مانند فراخوانی وب سرویس، خواندن فایل، یا عملیات پایگاه داده) را بدون مسدود کردن UI Thread یا Main Thread فراهم می‌کند. این الگو باعث بهبود پاسخ‌دهی (Responsiveness) برنامه و استفاده بهتر از منابع سیستم می‌شود.

کلمات کلیدی:
مثال پایه:
using System;
using System.Net.Http;
using System.Threading.Tasks;

public class AsyncExample
{
    // متد async که Task برمی‌گرداند
    public static async Task DownloadDataAsync(string url)
    {
        using (HttpClient client = new HttpClient())
        {
            try
            {
                Console.WriteLine("Starting download...");
                
                // await باعث می‌شود thread آزاد شود تا کارهای دیگر انجام دهد
                string content = await client.GetStringAsync(url);
                
                Console.WriteLine($"Downloaded {content.Length} characters");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }
    }

    // متد async که Task<T> برمی‌گرداند
    public static async Task<int> CalculateAsync(int number)
    {
        Console.WriteLine("Starting calculation...");
        
        // شبیه‌سازی عملیات طولانی‌مدت
        await Task.Delay(2000); // 2 ثانیه انتظار
        
        int result = number * number;
        Console.WriteLine($"Calculation completed: {result}");
        return result;
    }
}
مثال استفاده:
public static async Task DemonstrateAsync()
{
    Console.WriteLine("Main method started");

    // فراخوانی متد async
    Task downloadTask = DownloadDataAsync("https://api.github.com");
    Task<int> calculationTask = CalculateAsync(5);

    // انجام کارهای دیگر در همین حین
    Console.WriteLine("Doing other work while waiting...");
    
    // منتظر تکمیل هر دو عملیات
    await downloadTask;
    int result = await calculationTask;
    
    Console.WriteLine($"Final result: {result}");
    Console.WriteLine("Main method completed");
}
مثال Parallel Execution:
public static async Task DemonstrateParallelExecution()
{
    Console.WriteLine("Starting parallel tasks...");
    
    // شروع همزمان چندین task
    Task<int> task1 = CalculateAsync(3);
    Task<int> task2 = CalculateAsync(4);
    Task<int> task3 = CalculateAsync(5);
    
    // منتظر تکمیل همه taskها
    int[] results = await Task.WhenAll(task1, task2, task3);
    
    Console.WriteLine($"Results: {string.Join(", ", results)}");
}
نکات مهم:

۳۷. Garbage Collection (GC) در C# چیست؟

پاسخ:

Garbage Collection (GC) یا جمع‌آوری خودکار زباله، فرآیند خودکار مدیریت حافظه در .NET است که مسئول شناسایی و آزادسازی حافظه اشیائی است که دیگر مورد استفاده قرار نمی‌گیرند. GC به طور خودکار اجرا می‌شود و برنامه‌نویس نیازی به مدیریت دستی حافظه ندارد، اما درک نحوه کارکرد آن برای بهینه‌سازی عملکرد مهم است.

نسل‌های GC (Generations):
مثال نحوه کارکرد GC:
using System;

public class GCExample
{
    public static void DemonstrateGC()
    {
        Console.WriteLine("Before creating objects:");
        PrintMemoryInfo();

        // ایجاد اشیاء زیاد
        for (int i = 0; i < 100000; i++)
        {
            var temp = new string('A', 1000); // ایجاد رشته‌های بزرگ
        }

        Console.WriteLine("\nAfter creating objects:");
        PrintMemoryInfo();

        // اجرای دستی GC
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        Console.WriteLine("\nAfter manual GC:");
        PrintMemoryInfo();
    }

    private static void PrintMemoryInfo()
    {
        Console.WriteLine($"Gen 0 collections: {GC.CollectionCount(0)}");
        Console.WriteLine($"Gen 1 collections: {GC.CollectionCount(1)}");
        Console.WriteLine($"Gen 2 collections: {GC.CollectionCount(2)}");
        Console.WriteLine($"Total memory: {GC.GetTotalMemory(false):N0} bytes");
    }
}
مثال Finalizer و IDisposable:
public class ResourceManager : IDisposable
{
    private bool disposed = false;
    private IntPtr unmanagedResource; // منبع unmanaged

    // Finalizer - فقط در صورت عدم فراخوانی Dispose اجرا می‌شود
    ~ResourceManager()
    {
        Dispose(false);
    }

    // پیاده‌سازی IDisposable
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this); // جلوگیری از اجرای Finalizer
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // آزادسازی منابع managed
                Console.WriteLine("Disposing managed resources");
            }

            // آزادسازی منابع unmanaged
            Console.WriteLine("Disposing unmanaged resources");
            
            disposed = true;
        }
    }
}

// استفاده با using statement
public static void DemonstrateResourceManagement()
{
    using (var resource = new ResourceManager())
    {
        // استفاده از resource
        Console.WriteLine("Using resource");
    } // Dispose به طور خودکار فراخوانی می‌شود
}
بهترین شیوه‌ها:

۳۸. Reflection در C# چیست؟

پاسخ:

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

کاربردهای Reflection:
مثال بررسی نوع داده:
using System;
using System.Reflection;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    private string ssn;

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

    public void SayHello()
    {
        Console.WriteLine($"Hello, I'm {Name}");
    }

    private void SetSSN(string socialSecurityNumber)
    {
        ssn = socialSecurityNumber;
    }
}

public class ReflectionExample
{
    public static void DemonstrateTypeInformation()
    {
        Type personType = typeof(Person);
        
        Console.WriteLine($"Type Name: {personType.Name}");
        Console.WriteLine($"Full Name: {personType.FullName}");
        Console.WriteLine($"Namespace: {personType.Namespace}");

        // بررسی Properties
        Console.WriteLine("\nProperties:");
        PropertyInfo[] properties = personType.GetProperties();
        foreach (PropertyInfo prop in properties)
        {
            Console.WriteLine($"- {prop.Name} ({prop.PropertyType.Name})");
        }

        // بررسی Methods
        Console.WriteLine("\nMethods:");
        MethodInfo[] methods = personType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
        foreach (MethodInfo method in methods)
        {
            Console.WriteLine($"- {method.Name}");
        }
    }
}
مثال ایجاد شیء و فراخوانی متد:
public static void DemonstrateDynamicInvocation()
{
    Type personType = typeof(Person);
    
    // ایجاد شیء با سازنده پیش‌فرض
    object personInstance = Activator.CreateInstance(personType);
    
    // تنظیم مقدار Property
    PropertyInfo nameProperty = personType.GetProperty("Name");
    nameProperty.SetValue(personInstance, "احمد");
    
    PropertyInfo ageProperty = personType.GetProperty("Age");
    ageProperty.SetValue(personInstance, 25);
    
    // فراخوانی متد
    MethodInfo sayHelloMethod = personType.GetMethod("SayHello");
    sayHelloMethod.Invoke(personInstance, null);
    
    // دسترسی به متد private
    MethodInfo setSSNMethod = personType.GetMethod("SetSSN", BindingFlags.NonPublic | BindingFlags.Instance);
    setSSNMethod.Invoke(personInstance, new object[] { "123-45-6789" });
}
مثال Generic Type:
public static void DemonstrateGenericReflection()
{
    // ایجاد List<string> با Reflection
    Type listType = typeof(List<>);
    Type stringListType = listType.MakeGenericType(typeof(string));
    object stringList = Activator.CreateInstance(stringListType);
    
    // اضافه کردن عنصر
    MethodInfo addMethod = stringListType.GetMethod("Add");
    addMethod.Invoke(stringList, new object[] { "Hello" });
    addMethod.Invoke(stringList, new object[] { "World" });
    
    // دریافت تعداد عناصر
    PropertyInfo countProperty = stringListType.GetProperty("Count");
    int count = (int)countProperty.GetValue(stringList);
    Console.WriteLine($"List count: {count}");
}
نکات مهم:

۳۹. Attributes در C# چیست؟

پاسخ:

Attributes (ویژگی‌ها) ابزاری برای اضافه کردن metadata به عناصر کد هستند (مانند کلاس‌ها، متدها، ویژگی‌ها، فیلدها). آن‌ها اطلاعات اضافی درباره عناصر کد ارائه می‌دهند که می‌تواند توسط کامپایلر، runtime، یا ابزارهای دیگر استفاده شود. Attributes رفتار کد را تغییر نمی‌دهند، بلکه اطلاعات توصیفی فراهم می‌کنند.

انواع Attributes:
مثال استفاده از Built-in Attributes:
using System;
using System.ComponentModel;

public class AttributeExample
{
    [Obsolete("This method is deprecated. Use NewMethod instead.")]
    public void OldMethod()
    {
        Console.WriteLine("This is the old method");
    }

    public void NewMethod()
    {
        Console.WriteLine("This is the new method");
    }

    [Description("This property represents the user's full name")]
    public string FullName { get; set; }

    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
    public void CriticalMethod()
    {
        Console.WriteLine("This method should not be inlined");
    }
}
مثال Custom Attribute:
// تعریف Custom Attribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class AuthorAttribute : Attribute
{
    public string Name { get; }
    public string Email { get; set; }
    public DateTime Date { get; set; }

    public AuthorAttribute(string name)
    {
        Name = name;
        Date = DateTime.Now;
    }
}

// استفاده از Custom Attribute
[Author("احمد محمدی", Email = "[email protected]")]
[Author("فاطمه احمدی", Email = "[email protected]")]
public class Calculator
{
    [Author("علی رضایی")]
    public int Add(int a, int b)
    {
        return a + b;
    }

    [Author("زهرا محمدی")]
    public int Multiply(int a, int b)
    {
        return a * b;
    }
}
مثال خواندن Attributes با Reflection:
public static void ReadAttributes()
{
    Type calculatorType = typeof(Calculator);
    
    // خواندن attributes کلاس
    AuthorAttribute[] classAuthors = (AuthorAttribute[])calculatorType.GetCustomAttributes(typeof(AuthorAttribute), false);
    
    Console.WriteLine("Class Authors:");
    foreach (AuthorAttribute author in classAuthors)
    {
        Console.WriteLine($"- {author.Name} ({author.Email}) - {author.Date:yyyy-MM-dd}");
    }

    // خواندن attributes متدها
    MethodInfo[] methods = calculatorType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
    
    foreach (MethodInfo method in methods)
    {
        AuthorAttribute methodAuthor = (AuthorAttribute)method.GetCustomAttribute(typeof(AuthorAttribute));
        if (methodAuthor != null)
        {
            Console.WriteLine($"Method {method.Name} by: {methodAuthor.Name}");
        }
    }
}
مثال Validation Attribute:
// Custom Validation Attribute
[AttributeUsage(AttributeTargets.Property)]
public class RangeValidationAttribute : Attribute
{
    public int Min { get; }
    public int Max { get; }

    public RangeValidationAttribute(int min, int max)
    {
        Min = min;
        Max = max;
    }

    public bool IsValid(object value)
    {
        if (value is int intValue)
        {
            return intValue >= Min && intValue <= Max;
        }
        return false;
    }
}

public class Student
{
    public string Name { get; set; }
    
    [RangeValidation(0, 100)]
    public int Grade { get; set; }
    
    [RangeValidation(18, 65)]
    public int Age { get; set; }
}

// Validation Logic
public static bool ValidateObject(object obj)
{
    Type type = obj.GetType();
    PropertyInfo[] properties = type.GetProperties();
    
    foreach (PropertyInfo property in properties)
    {
        RangeValidationAttribute validation = property.GetCustomAttribute<RangeValidationAttribute>();
        if (validation != null)
        {
            object value = property.GetValue(obj);
            if (!validation.IsValid(value))
            {
                Console.WriteLine($"Validation failed for {property.Name}: {value}");
                return false;
            }
        }
    }
    return true;
}

۴۰. Serialization در C# چیست؟

پاسخ:

Serialization فرآیند تبدیل یک شیء به فرمتی است که قابل ذخیره‌سازی یا انتقال باشد (مانند JSON، XML، یا Binary). Deserialization فرآیند معکوس است که داده‌های serialize شده را دوباره به شیء تبدیل می‌کند. این فرآیند برای ذخیره‌سازی داده‌ها، انتقال داده‌ها بین سیستم‌ها، و کار با Web APIs بسیار مهم است.

انواع Serialization:
مثال JSON Serialization:
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public DateTime BirthDate { get; set; }
    
    [JsonIgnore] // این ویژگی serialize نمی‌شود
    public string Password { get; set; }
    
    [JsonPropertyName("email_address")] // نام متفاوت در JSON
    public string Email { get; set; }
}

public class SerializationExample
{
    public static void DemonstrateJsonSerialization()
    {
        // ایجاد شیء
        Person person = new Person
        {
            Name = "احمد محمدی",
            Age = 30,
            BirthDate = new DateTime(1993, 5, 15),
            Email = "[email protected]",
            Password = "secret123" // این serialize نمی‌شود
        };

        // Serialization
        JsonSerializerOptions options = new JsonSerializerOptions
        {
            WriteIndented = true, // فرمت زیبا
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        };
        
        string jsonString = JsonSerializer.Serialize(person, options);
        Console.WriteLine("Serialized JSON:");
        Console.WriteLine(jsonString);

        // Deserialization
        Person deserializedPerson = JsonSerializer.Deserialize<Person>(jsonString, options);
        Console.WriteLine($"\nDeserialized: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");
    }
}
مثال XML Serialization:
using System;
using System.IO;
using System.Xml.Serialization;

[XmlRoot("Student")]
public class Student
{
    [XmlElement("FullName")]
    public string Name { get; set; }
    
    [XmlAttribute("id")]
    public int Id { get; set; }
    
    [XmlArray("Courses")]
    [XmlArrayItem("Course")]
    public List<string> Courses { get; set; }
    
    public Student()
    {
        Courses = new List<string>();
    }
}

public static void DemonstrateXmlSerialization()
{
    Student student = new Student
    {
        Id = 123,
        Name = "فاطمه احمدی",
        Courses = new List<string> { "ریاضی", "فیزیک", "کامپیوتر" }
    };

    // XML Serialization
    XmlSerializer serializer = new XmlSerializer(typeof(Student));
    
    using (StringWriter writer = new StringWriter())
    {
        serializer.Serialize(writer, student);
        string xmlString = writer.ToString();
        Console.WriteLine("XML Serialized:");
        Console.WriteLine(xmlString);
        
        // XML Deserialization
        using (StringReader reader = new StringReader(xmlString))
        {
            Student deserializedStudent = (Student)serializer.Deserialize(reader);
            Console.WriteLine($"Deserialized: {deserializedStudent.Name} (ID: {deserializedStudent.Id})");
        }
    }
}
مثال Custom JSON Converter:
public class DateOnlyJsonConverter : JsonConverter<DateTime>
{
    private const string DateFormat = "yyyy-MM-dd";

    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateTime.ParseExact(reader.GetString(), DateFormat, null);
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString(DateFormat));
    }
}

public class Event
{
    public string Title { get; set; }
    
    [JsonConverter(typeof(DateOnlyJsonConverter))]
    public DateTime EventDate { get; set; }
}

public static void DemonstrateCustomConverter()
{
    Event eventObj = new Event
    {
        Title = "کنفرانس برنامه‌نویسی",
        EventDate = new DateTime(2024, 12, 25)
    };

    string json = JsonSerializer.Serialize(eventObj);
    Console.WriteLine($"Custom serialized: {json}");
    // خروجی: {"Title":"کنفرانس برنامه‌نویسی","EventDate":"2024-12-25"}
}
بهترین شیوه‌ها:

۴۱. using Statement در C# چیست؟

پاسخ:

using statement یک ساختار کنترلی در C# است که برای مدیریت خودکار منابع (Automatic Resource Management) استفاده می‌شود. این statement تضمین می‌کند که منابع قابل تصرف (Disposable Resources) به صورت خودکار و در زمان مناسب آزاد شوند، حتی اگر استثنا رخ دهد. using statement با اشیائی که رابط IDisposable را پیاده‌سازی کرده‌اند کار می‌کند.

مزایای using statement:
مثال با فایل:
using System;
using System.IO;

public class UsingStatementExample
{
    public static void DemonstrateUsingStatement()
    {
        // using statement با فایل
        using (FileStream file = new FileStream("example.txt", FileMode.Create))
        using (StreamWriter writer = new StreamWriter(file))
        {
            writer.WriteLine("Hello, World!");
            writer.WriteLine("This is a test file.");
            // Dispose() به صورت خودکار فراخوانی می‌شود
        } // فایل در اینجا بسته می‌شود

        // معادل کد بالا با try-finally
        FileStream file2 = null;
        StreamWriter writer2 = null;
        try
        {
            file2 = new FileStream("example2.txt", FileMode.Create);
            writer2 = new StreamWriter(file2);
            writer2.WriteLine("Hello, World!");
        }
        finally
        {
            writer2?.Dispose();
            file2?.Dispose();
        }
    }
}
مثال با پایگاه داده:
using System.Data.SqlClient;

public static void DatabaseExample()
{
    string connectionString = "Server=.;Database=TestDB;Integrated Security=true;";
    
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
        
        using (SqlCommand command = new SqlCommand("SELECT * FROM Users", connection))
        using (SqlDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                Console.WriteLine($"User: {reader["Name"]}");
            }
            // reader, command, و connection همگی به صورت خودکار dispose می‌شوند
        }
    }
}
using declaration (C# 8.0+):
public static void ModernUsingExample()
{
    using var file = new FileStream("modern.txt", FileMode.Create);
    using var writer = new StreamWriter(file);
    
    writer.WriteLine("Modern using declaration");
    writer.WriteLine("No braces needed!");
    
    // Dispose به صورت خودکار در انتهای scope فراخوانی می‌شود
}

۴۲. static keyword در C# چیست؟

پاسخ:

static keyword در C# برای تعریف اعضایی استفاده می‌شود که به کلاس تعلق دارند، نه به نمونه‌های (instances) آن. اعضای static بدون نیاز به ایجاد شیء از کلاس قابل دسترسی هستند و در تمام طول اجرای برنامه در حافظه باقی می‌مانند. فقط یک کپی از هر عضو static در حافظه وجود دارد که بین تمام instances کلاس مشترک است.

انواع اعضای static:
مثال Static Members:
public class Counter
{
    // Static field - بین تمام instances مشترک است
    private static int totalCount = 0;
    
    // Instance field - هر instance مقدار جداگانه‌ای دارد
    private int instanceId;

    // Static property
    public static int TotalCount 
    { 
        get { return totalCount; } 
    }

    // Constructor
    public Counter()
    {
        totalCount++; // افزایش شمارنده کلی
        instanceId = totalCount;
    }

    // Static method
    public static void ResetCounter()
    {
        totalCount = 0;
        Console.WriteLine("Counter reset to zero");
    }

    // Instance method
    public void ShowInfo()
    {
        Console.WriteLine($"Instance ID: {instanceId}, Total Count: {totalCount}");
    }
}

public static void DemonstrateStatic()
{
    Console.WriteLine($"Initial count: {Counter.TotalCount}"); // خروجی: 0

    Counter c1 = new Counter();
    Counter c2 = new Counter();
    Counter c3 = new Counter();

    c1.ShowInfo(); // Instance ID: 1, Total Count: 3
    c2.ShowInfo(); // Instance ID: 2, Total Count: 3
    c3.ShowInfo(); // Instance ID: 3, Total Count: 3

    Console.WriteLine($"Total instances created: {Counter.TotalCount}"); // خروجی: 3

    Counter.ResetCounter(); // فراخوانی static method
}
مثال Static Class:
// Static class - نمی‌توان از آن instance ایجاد کرد
public static class MathUtility
{
    public static double PI = 3.14159;

    public static double CalculateCircleArea(double radius)
    {
        return PI * radius * radius;
    }

    public static double CalculateRectangleArea(double width, double height)
    {
        return width * height;
    }

    public static int GetRandomNumber(int min, int max)
    {
        Random random = new Random();
        return random.Next(min, max);
    }
}

// استفاده
public static void UseStaticClass()
{
    double area = MathUtility.CalculateCircleArea(5);
    Console.WriteLine($"Circle area: {area}");

    int randomNum = MathUtility.GetRandomNumber(1, 100);
    Console.WriteLine($"Random number: {randomNum}");
}
مثال Static Constructor:
public class Configuration
{
    public static string DatabaseConnection { get; private set; }
    public static string ApiKey { get; private set; }

    // Static constructor - فقط یک بار اجرا می‌شود
    static Configuration()
    {
        Console.WriteLine("Static constructor called");
        DatabaseConnection = "Server=localhost;Database=MyApp;";
        ApiKey = "ABC123XYZ789";
        
        // اینجا می‌توان فایل config خواند یا تنظیمات اولیه انجام داد
    }

    public static void ShowConfiguration()
    {
        Console.WriteLine($"DB: {DatabaseConnection}");
        Console.WriteLine($"API Key: {ApiKey}");
    }
}
نکات مهم:

۴۳. virtual keyword در C# چه کاربردی دارد؟

پاسخ:

virtual keyword برای مشخص کردن متد، Property، ایندکسر یا رویداد در کلاس پایه استفاده می‌شود که می‌تواند توسط کلاس‌های مشتق شده بازنویسی (Override) شود. این کلمه کلیدی پایه و اساس Run-time Polymorphism (چندریختی زمان اجرا) را فراهم می‌کند و به کلاس‌های مشتق شده اجازه می‌دهد تا پیاده‌سازی خاص خود را برای آن عضو ارائه دهند.

ویژگی‌های virtual:
مثال:
public class Shape
{
    public virtual void Draw() // متد virtual
    {
        Console.WriteLine("Drawing a generic shape.");
    }

    public virtual double Area // Property virtual
    {
        get { return 0; }
    }

    public virtual string GetInfo()
    {
        return "This is a generic shape";
    }
}

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

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

    public override void Draw() // بازنویسی متد Draw
    {
        Console.WriteLine($"Drawing a circle with radius {Radius}.");
    }

    public override double Area // بازنویسی Property Area
    {
        get { return Math.PI * Radius * Radius; }
    }

    public override string GetInfo()
    {
        return $"Circle with radius {Radius} and area {Area:F2}";
    }
}

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 void Draw() // بازنویسی متد Draw
    {
        Console.WriteLine($"Drawing a rectangle {Width}x{Height}.");
    }

    public override double Area // بازنویسی Property Area
    {
        get { return Width * Height; }
    }
}
مثال Polymorphism:
public static void DemonstrateVirtualKeyword()
{
    // آرایه‌ای از اشکال مختلف
    Shape[] shapes = {
        new Shape(),
        new Circle(5),
        new Rectangle(4, 6),
        new Circle(3)
    };

    foreach (Shape shape in shapes)
    {
        shape.Draw(); // متد مناسب هر شکل فراخوانی می‌شود
        Console.WriteLine($"Area: {shape.Area:F2}");
        Console.WriteLine($"Info: {shape.GetInfo()}");
        Console.WriteLine("---");
    }
}

// خروجی:
// Drawing a generic shape.
// Area: 0.00
// Info: This is a generic shape
// ---
// Drawing a circle with radius 5.
// Area: 78.54
// Info: Circle with radius 5 and area 78.54
// ---
// Drawing a rectangle 4x6.
// Area: 24.00
// Info: This is a generic shape
// ---
مثال با base keyword:
public class Employee
{
    public string Name { get; set; }
    public decimal Salary { get; set; }

    public virtual decimal CalculateBonus()
    {
        return Salary * 0.1m; // 10% پاداش پایه
    }

    public virtual void ShowDetails()
    {
        Console.WriteLine($"Employee: {Name}, Salary: ${Salary:F2}");
    }
}

public class Manager : Employee
{
    public int TeamSize { get; set; }

    public override decimal CalculateBonus()
    {
        // استفاده از پیاده‌سازی پایه + پاداش اضافی
        decimal baseBonus = base.CalculateBonus();
        decimal managerBonus = TeamSize * 100; // $100 برای هر عضو تیم
        return baseBonus + managerBonus;
    }

    public override void ShowDetails()
    {
        base.ShowDetails(); // فراخوانی متد پایه
        Console.WriteLine($"Team Size: {TeamSize}, Bonus: ${CalculateBonus():F2}");
    }
}

۴۴. override keyword در C# چه کاربردی دارد؟

پاسخ:

override keyword برای گسترش یا اصلاح پیاده‌سازی یک متد، Property، ایندکسر یا رویداد ارث‌بری شده از کلاس پایه استفاده می‌شود. این کلمه کلیدی تنها زمانی قابل استفاده است که عضو مربوطه در کلاس پایه با virtual، abstract یا override مشخص شده باشد. override امکان پیاده‌سازی Polymorphism را فراهم می‌کند.

ویژگی‌های override:
مثال:
public class Vehicle
{
    public string Brand { get; set; }
    public int Year { get; set; }

    public Vehicle(string brand, int year)
    {
        Brand = brand;
        Year = year;
    }

    public virtual void Start()
    {
        Console.WriteLine($"{Brand} vehicle is starting...");
    }

    public virtual void Stop()
    {
        Console.WriteLine($"{Brand} vehicle is stopping...");
    }

    public virtual double CalculateFuelConsumption(double distance)
    {
        return distance * 0.1; // مصرف پیش‌فرض
    }

    public override string ToString() // بازنویسی متد ToString از System.Object
    {
        return $"{Brand} ({Year})";
    }
}

public class Car : Vehicle
{
    public int NumberOfDoors { get; set; }

    public Car(string brand, int year, int doors) : base(brand, year)
    {
        NumberOfDoors = doors;
    }

    public override void Start()
    {
        Console.WriteLine("Checking car systems...");
        base.Start(); // فراخوانی پیاده‌سازی کلاس پایه
        Console.WriteLine("Car is ready to drive!");
    }

    public override double CalculateFuelConsumption(double distance)
    {
        // ماشین‌ها مصرف کمتری دارند
        return distance * 0.08;
    }

    public override string ToString()
    {
        return $"{base.ToString()} - {NumberOfDoors} doors";
    }
}

public class Truck : Vehicle
{
    public double LoadCapacity { get; set; }

    public Truck(string brand, int year, double capacity) : base(brand, year)
    {
        LoadCapacity = capacity;
    }

    public override void Start()
    {
        Console.WriteLine("Warming up truck engine...");
        base.Start();
        Console.WriteLine("Truck is ready for heavy duty!");
    }

    public override double CalculateFuelConsumption(double distance)
    {
        // کامیون‌ها مصرف بیشتری دارند
        return distance * 0.15;
    }
}
مثال استفاده:
public static void DemonstrateOverrideKeyword()
{
    Vehicle[] vehicles = {
        new Car("Toyota", 2020, 4),
        new Truck("Volvo", 2019, 10.5),
        new Car("BMW", 2021, 2)
    };

    foreach (Vehicle vehicle in vehicles)
    {
        Console.WriteLine($"Vehicle: {vehicle}"); // ToString override شده فراخوانی می‌شود
        vehicle.Start(); // Start override شده فراخوانی می‌شود
        
        double fuel = vehicle.CalculateFuelConsumption(100);
        Console.WriteLine($"Fuel consumption for 100km: {fuel:F2} liters");
        
        vehicle.Stop();
        Console.WriteLine("---");
    }
}
مثال با Abstract Base Class:
public abstract class Animal
{
    public string Name { get; set; }

    public Animal(string name)
    {
        Name = name;
    }

    // Abstract method - باید در کلاس مشتق شده override شود
    public abstract void MakeSound();

    // Virtual method - می‌تواند override شود
    public virtual void Sleep()
    {
        Console.WriteLine($"{Name} is sleeping...");
    }
}

public class Dog : Animal
{
    public Dog(string name) : base(name) { }

    public override void MakeSound()
    {
        Console.WriteLine($"{Name} says: Woof! Woof!");
    }

    public override void Sleep()
    {
        Console.WriteLine($"{Name} is sleeping in the doghouse...");
    }
}

public class Cat : Animal
{
    public Cat(string name) : base(name) { }

    public override void MakeSound()
    {
        Console.WriteLine($"{Name} says: Meow! Meow!");
    }

    // Sleep متد را override نکردیم، پس پیاده‌سازی پایه استفاده می‌شود
}

۴۵. new keyword در C# چه کاربردهایی دارد؟

پاسخ:

new keyword در C# دارای چندین کاربرد متفاوت است که هر کدام در موقعیت‌های خاصی استفاده می‌شوند.

کاربردهای new keyword:
۱. Object Instantiation:
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public Person() { }

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

public static void DemonstrateObjectCreation()
{
    // ایجاد شیء با سازنده پیش‌فرض
    Person person1 = new Person();
    person1.Name = "احمد";
    person1.Age = 25;

    // ایجاد شیء با سازنده پارامتردار
    Person person2 = new Person("فاطمه", 30);

    // ایجاد آرایه
    int[] numbers = new int[5];
    string[] names = new string[] { "علی", "زهرا", "حسن" };

    // Object initializer syntax
    Person person3 = new Person 
    { 
        Name = "محمد", 
        Age = 28 
    };
}
۲. Member Hiding (Shadowing):
public class BaseClass
{
    public void Show()
    {
        Console.WriteLine("Base Show method");
    }

    public virtual void Display()
    {
        Console.WriteLine("Base Display method");
    }

    public string Message { get; set; } = "Base Message";
}

public class DerivedClass : BaseClass
{
    // پنهان کردن متد Show از کلاس پایه
    public new void Show()
    {
        Console.WriteLine("Derived Show method");
    }

    // بازنویسی متد Display (Polymorphism)
    public override void Display()
    {
        Console.WriteLine("Derived Display method");
    }

    // پنهان کردن Property از کلاس پایه
    public new string Message { get; set; } = "Derived Message";
}

public static void DemonstrateMemberHiding()
{
    DerivedClass derived = new DerivedClass();
    derived.Show();    // خروجی: Derived Show method
    derived.Display(); // خروجی: Derived Display method

    BaseClass baseRef = new DerivedClass();
    baseRef.Show();    // خروجی: Base Show method (new باعث hiding می‌شود، نه override)
    baseRef.Display(); // خروجی: Derived Display method (override باعث polymorphism می‌شود)

    Console.WriteLine($"Derived Message: {derived.Message}");
    Console.WriteLine($"Base Message: {baseRef.Message}");
}
۳. Generic Type Constraint:
// Generic class با new() constraint
public class Factory<T> where T : new()
{
    public T CreateInstance()
    {
        return new T(); // امکان ایجاد شیء از نوع T
    }

    public List<T> CreateMultipleInstances(int count)
    {
        List<T> instances = new List<T>();
        for (int i = 0; i < count; i++)
        {
            instances.Add(new T());
        }
        return instances;
    }
}

public class Product
{
    public string Name { get; set; } = "Default Product";
    public decimal Price { get; set; } = 0;
}

public static void DemonstrateGenericConstraint()
{
    Factory<Product> productFactory = new Factory<Product>();
    Product product = productFactory.CreateInstance();
    Console.WriteLine($"Created: {product.Name}");

    List<Product> products = productFactory.CreateMultipleInstances(3);
    Console.WriteLine($"Created {products.Count} products");

    // Factory<string> stringFactory = new Factory<string>(); // خطا! string سازنده بدون پارامتر ندارد
}
۴. Anonymous Types:
public static void DemonstrateAnonymousTypes()
{
    // ایجاد anonymous type
    var person = new { Name = "علی", Age = 25, City = "تهران" };
    Console.WriteLine($"Person: {person.Name}, {person.Age}, {person.City}");

    // آرایه از anonymous types
    var people = new[]
    {
        new { Name = "احمد", Age = 30 },
        new { Name = "فاطمه", Age = 28 },
        new { Name = "حسن", Age = 35 }
    };

    foreach (var p in people)
    {
        Console.WriteLine($"{p.Name} is {p.Age} years old");
    }

    // استفاده در LINQ
    var products = new[]
    {
        new { Name = "لپ‌تاپ", Price = 1500, Category = "الکترونیک" },
        new { Name = "کتاب", Price = 25, Category = "آموزش" }
    };

    var expensiveProducts = products
        .Where(p => p.Price > 100)
        .Select(p => new { p.Name, p.Price })
        .ToArray();
}
نکات مهم:

۴۶. struct در C# چیست و چه تفاوتی با class دارد؟

پاسخ:

struct (ساختار) یک نوع مقداری (Value Type) است، در حالی که class یک نوع ارجاعی (Reference Type) است. این تفاوت اساسی، پیامدهای مهمی در نحوه ذخیره‌سازی در حافظه، رفتار انتساب و عملکرد دارد. struct برای داده‌های کوچک و ساده که نیاز به کپی شدن دارند مناسب است.

تفاوت‌های اصلی:
مثال تعریف struct:
// تعریف یک Struct
public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }

    public double DistanceFromOrigin()
    {
        return Math.Sqrt(X * X + Y * Y);
    }

    public void Move(int dx, int dy)
    {
        X += dx;
        Y += dy;
    }

    public override string ToString()
    {
        return $"({X}, {Y})";
    }
}

// تعریف یک Class مشابه
public class PointClass
{
    public int X { get; set; }
    public int Y { get; set; }

    public PointClass(int x, int y)
    {
        X = x;
        Y = y;
    }

    public double DistanceFromOrigin()
    {
        return Math.Sqrt(X * X + Y * Y);
    }

    public void Move(int dx, int dy)
    {
        X += dx;
        Y += dy;
    }

    public override string ToString()
    {
        return $"({X}, {Y})";
    }
}
مثال مقایسه رفتار:
public static void CompareStructAndClass()
{
    Console.WriteLine("=== Struct Example (Value Type) ===");
    Point p1 = new Point(10, 20);
    Point p2 = p1; // کپی کامل از p1 به p2
    
    Console.WriteLine($"Before: p1 = {p1}, p2 = {p2}");
    
    p2.Move(5, 5); // فقط p2 تغییر می‌کند
    Console.WriteLine($"After moving p2: p1 = {p1}, p2 = {p2}");

    Console.WriteLine("\n=== Class Example (Reference Type) ===");
    PointClass pc1 = new PointClass(10, 20);
    PointClass pc2 = pc1; // pc2 به همان شیء pc1 اشاره می‌کند
    
    Console.WriteLine($"Before: pc1 = {pc1}, pc2 = {pc2}");
    
    pc2.Move(5, 5); // هر دو pc1 و pc2 تغییر می‌کنند
    Console.WriteLine($"After moving pc2: pc1 = {pc1}, pc2 = {pc2}");

    Console.WriteLine("\n=== Memory and Performance ===");
    // struct معمولاً سریعتر است برای داده‌های کوچک
    Point[] points = new Point[1000];
    PointClass[] pointClasses = new PointClass[1000];
    
    // پر کردن آرایه struct - فقط Stack استفاده می‌شود
    for (int i = 0; i < points.Length; i++)
    {
        points[i] = new Point(i, i * 2);
    }
    
    // پر کردن آرایه class - Heap و GC درگیر می‌شود
    for (int i = 0; i < pointClasses.Length; i++)
    {
        pointClasses[i] = new PointClass(i, i * 2);
    }
}
مثال Immutable Struct:
// Immutable struct - بهترین شیوه برای struct
public readonly struct ImmutablePoint
{
    public int X { get; }
    public int Y { get; }

    public ImmutablePoint(int x, int y)
    {
        X = x;
        Y = y;
    }

    public ImmutablePoint Move(int dx, int dy)
    {
        return new ImmutablePoint(X + dx, Y + dy); // شیء جدید برمی‌گرداند
    }

    public double DistanceFromOrigin => Math.Sqrt(X * X + Y * Y);

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

public static void DemonstrateImmutableStruct()
{
    ImmutablePoint original = new ImmutablePoint(10, 20);
    ImmutablePoint moved = original.Move(5, 5);
    
    Console.WriteLine($"Original: {original}");
    Console.WriteLine($"Moved: {moved}");
    Console.WriteLine($"Distance: {original.DistanceFromOrigin:F2}");
}
چه زمانی از struct استفاده کنیم؟

۴۷. Nullable Types در C# چیست؟

پاسخ:

Nullable Types امکان انتساب مقدار null را به Value Typeها فراهم می‌کنند. به طور پیش‌فرض، Value Typeها (مانند int، bool، DateTime) نمی‌توانند مقدار null داشته باشند، اما با استفاده از Nullable Types، می‌توانید این محدودیت را برطرف کنید. این ویژگی به خصوص در کار با پایگاه‌های داده که ممکن است فیلدهای null داشته باشند بسیار مفید است.

نحوه تعریف Nullable Types:
مثال پایه:
public static void DemonstrateNullableTypes()
{
    // تعریف Nullable Types
    int? nullableInt = null;
    bool? nullableBool = true;
    DateTime? nullableDate = DateTime.Now;
    double? nullableDouble = null;

    Console.WriteLine("=== بررسی وجود مقدار ===");
    
    // بررسی وجود مقدار با HasValue
    if (nullableInt.HasValue)
    {
        Console.WriteLine($"nullableInt دارای مقدار است: {nullableInt.Value}");
    }
    else
    {
        Console.WriteLine("nullableInt مقدار null دارد");
    }

    if (nullableBool.HasValue)
    {
        Console.WriteLine($"nullableBool دارای مقدار است: {nullableBool.Value}");
    }

    Console.WriteLine("\n=== استفاده از GetValueOrDefault ===");
    
    // استفاده از GetValueOrDefault
    Console.WriteLine($"Int value or default: {nullableInt.GetValueOrDefault()}"); // 0
    Console.WriteLine($"Int value or custom default: {nullableInt.GetValueOrDefault(100)}"); // 100
    Console.WriteLine($"Double value or default: {nullableDouble.GetValueOrDefault(3.14)}"); // 3.14

    Console.WriteLine("\n=== Null Coalescing Operator (??) ===");
    
    // Null Coalescing Operator (??)
    int actualInt = nullableInt ?? -1; // اگر null باشد، -1 استفاده کن
    double actualDouble = nullableDouble ?? 0.0;
    
    Console.WriteLine($"Actual int: {actualInt}");
    Console.WriteLine($"Actual double: {actualDouble}");
}
مثال کاربردی با پایگاه داده:
public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? Age { get; set; } // ممکن است در پایگاه داده null باشد
    public DateTime? HireDate { get; set; }
    public decimal? Salary { get; set; }
    public bool? IsActive { get; set; }

    public void DisplayInfo()
    {
        Console.WriteLine($"ID: {Id}");
        Console.WriteLine($"Name: {Name}");
        
        // نمایش Age
        if (Age.HasValue)
        {
            Console.WriteLine($"Age: {Age.Value} years old");
        }
        else
        {
            Console.WriteLine("Age: Not specified");
        }

        // نمایش HireDate با استفاده از ??
        Console.WriteLine($"Hire Date: {HireDate?.ToString("yyyy-MM-dd") ?? "Not specified"}");
        
        // نمایش Salary
        Console.WriteLine($"Salary: {(Salary.HasValue ? $"${Salary.Value:N2}" : "Not disclosed")}");
        
        // نمایش Status
        string status = IsActive switch
        {
            true => "Active",
            false => "Inactive", 
            null => "Unknown"
        };
        Console.WriteLine($"Status: {status}");
    }

    public int GetAgeOrDefault(int defaultAge = 0)
    {
        return Age ?? defaultAge;
    }

    public bool IsEligibleForBonus()
    {
        // فقط اگر حقوق مشخص باشد و بیشتر از 50000 باشد
        return Salary.HasValue && Salary.Value > 50000;
    }
}

public static void DemonstrateEmployeeExample()
{
    Employee[] employees = {
        new Employee { Id = 1, Name = "احمد محمدی", Age = 30, HireDate = new DateTime(2020, 1, 15), Salary = 75000, IsActive = true },
        new Employee { Id = 2, Name = "فاطمه احمدی", Age = null, HireDate = null, Salary = 60000, IsActive = true },
        new Employee { Id = 3, Name = "علی رضایی", Age = 25, HireDate = new DateTime(2022, 6, 1), Salary = null, IsActive = false }
    };

    foreach (Employee emp in employees)
    {
        Console.WriteLine("===================");
        emp.DisplayInfo();
        Console.WriteLine($"Age (with default): {emp.GetAgeOrDefault(25)}");
        Console.WriteLine($"Eligible for bonus: {emp.IsEligibleForBonus()}");
    }
}
مثال Nullable Reference Types (C# 8.0+):
// در C# 8.0+ می‌توان nullable reference types را فعال کرد
#nullable enable

public class Person
{
    public string Name { get; set; } // Non-nullable
    public string? MiddleName { get; set; } // Nullable
    public string? LastName { get; set; } // Nullable

    public Person(string name)
    {
        Name = name; // باید مقدار داده شود
    }

    public string GetFullName()
    {
        // استفاده از null-conditional operator
        return $"{Name} {MiddleName?.Trim()} {LastName?.Trim()}".Trim();
    }

    public void UpdateName(string? newName)
    {
        if (!string.IsNullOrEmpty(newName))
        {
            Name = newName; // کامپایلر اطمینان دارد که null نیست
        }
    }
}

#nullable disable
بهترین شیوه‌ها:

۴۸. LINQ در C# چیست و چرا مفید است؟

پاسخ:

LINQ (Language Integrated Query) مجموعه‌ای از فناوری‌ها در .NET است که قابلیت‌های پرس‌وجو (Query) را مستقیماً به زبان C# اضافه می‌کند. LINQ به شما امکان می‌دهد تا با استفاده از یک syntax یکپارچه، داده‌ها را از منابع مختلف (مانند مجموعه‌های درون حافظه، پایگاه‌های داده SQL، اسناد XML) پرس‌وجو کنید. LINQ دو syntax اصلی دارد: Query Syntax و Method Syntax.

چرا LINQ مفید است؟
مثال Query Syntax:
using System;
using System.Linq;
using System.Collections.Generic;

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Major { get; set; }
    public double GPA { get; set; }
}

public static void DemonstrateQuerySyntax()
{
    List<Student> students = new List<Student>
    {
        new Student { Id = 1, Name = "احمد محمدی", Age = 20, Major = "کامپیوتر", GPA = 3.8 },
        new Student { Id = 2, Name = "فاطمه احمدی", Age = 22, Major = "ریاضی", GPA = 3.9 },
        new Student { Id = 3, Name = "علی رضایی", Age = 19, Major = "کامپیوتر", GPA = 3.5 },
        new Student { Id = 4, Name = "زهرا محمدی", Age = 21, Major = "فیزیک", GPA = 3.7 },
        new Student { Id = 5, Name = "حسن احمدی", Age = 23, Major = "ریاضی", GPA = 3.6 }
    };

    Console.WriteLine("=== Query Syntax Examples ===");

    // پیدا کردن دانشجویان کامپیوتر با GPA بالای 3.6
    var computerStudents = from student in students
                          where student.Major == "کامپیوتر" && student.GPA > 3.6
                          orderby student.GPA descending
                          select student;

    Console.WriteLine("دانشجویان کامپیوتر با GPA بالای 3.6:");
    foreach (var student in computerStudents)
    {
        Console.WriteLine($"- {student.Name}: GPA = {student.GPA}");
    }

    // گروه‌بندی بر اساس رشته تحصیلی
    var groupedByMajor = from student in students
                        group student by student.Major into majorGroup
                        select new 
                        { 
                            Major = majorGroup.Key, 
                            Count = majorGroup.Count(),
                            AverageGPA = majorGroup.Average(s => s.GPA)
                        };

    Console.WriteLine("\nآمار بر اساس رشته:");
    foreach (var group in groupedByMajor)
    {
        Console.WriteLine($"- {group.Major}: {group.Count} نفر، میانگین GPA: {group.AverageGPA:F2}");
    }
}
مثال Method Syntax:
public static void DemonstrateMethodSyntax()
{
    List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    Console.WriteLine("=== Method Syntax Examples ===");

    // فیلتر کردن اعداد زوج
    var evenNumbers = numbers
        .Where(n => n % 2 == 0)
        .ToList();
    Console.WriteLine($"اعداد زوج: {string.Join(", ", evenNumbers)}");

    // تبدیل به مربع و مرتب‌سازی نزولی
    var squares = numbers
        .Select(n => n * n)
        .OrderByDescending(n => n)
        .Take(5) // فقط 5 تای اول
        .ToList();
    Console.WriteLine($"5 مربع بزرگ: {string.Join(", ", squares)}");

    // ترکیب عملیات‌های مختلف
    var result = numbers
        .Where(n => n > 3)           // بزرگتر از 3
        .Select(n => new { Number = n, Square = n * n, IsEven = n % 2 == 0 })
        .Where(x => x.IsEven)        // فقط زوج‌ها
        .OrderBy(x => x.Number)      // مرتب‌سازی
        .ToList();

    Console.WriteLine("\nاعداد زوج بزرگتر از 3:");
    foreach (var item in result)
    {
        Console.WriteLine($"- عدد: {item.Number}, مربع: {item.Square}");
    }
}
مثال پیشرفته با Join:
public class Course
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Credits { get; set; }
}

public class Enrollment
{
    public int StudentId { get; set; }
    public int CourseId { get; set; }
    public double Grade { get; set; }
}

public static void DemonstrateAdvancedLinq()
{
    var courses = new List<Course>
    {
        new Course { Id = 1, Name = "ریاضی", Credits = 3 },
        new Course { Id = 2, Name = "فیزیک", Credits = 4 },
        new Course { Id = 3, Name = "برنامه‌نویسی", Credits = 3 }
    };

    var enrollments = new List<Enrollment>
    {
        new Enrollment { StudentId = 1, CourseId = 1, Grade = 18.5 },
        new Enrollment { StudentId = 1, CourseId = 3, Grade = 19.0 },
        new Enrollment { StudentId = 2, CourseId = 1, Grade = 17.5 },
        new Enrollment { StudentId = 2, CourseId = 2, Grade = 16.0 }
    };

    var students = new List<Student>
    {
        new Student { Id = 1, Name = "احمد محمدی", Age = 20, Major = "کامپیوتر" },
        new Student { Id = 2, Name = "فاطمه احمدی", Age = 22, Major = "ریاضی" }
    };

    // Join بین جداول مختلف
    var studentGrades = from student in students
                       join enrollment in enrollments on student.Id equals enrollment.StudentId
                       join course in courses on enrollment.CourseId equals course.Id
                       select new
                       {
                           StudentName = student.Name,
                           CourseName = course.Name,
                           Grade = enrollment.Grade,
                           Credits = course.Credits
                       };

    Console.WriteLine("=== نمرات دانشجویان ===");
    foreach (var grade in studentGrades)
    {
        Console.WriteLine($"{grade.StudentName} - {grade.CourseName}: {grade.Grade} ({grade.Credits} واحد)");
    }

    // محاسبه میانگین وزنی
    var studentAverages = studentGrades
        .GroupBy(g => g.StudentName)
        .Select(group => new
        {
            StudentName = group.Key,
            WeightedAverage = group.Sum(g => g.Grade * g.Credits) / group.Sum(g => g.Credits),
            TotalCredits = group.Sum(g => g.Credits)
        });

    Console.WriteLine("\n=== میانگین وزنی دانشجویان ===");
    foreach (var avg in studentAverages)
    {
        Console.WriteLine($"{avg.StudentName}: {avg.WeightedAverage:F2} ({avg.TotalCredits} واحد)");
    }
}
مثال LINQ با String:
public static void DemonstrateLinqWithStrings()
{
    string text = "LINQ در C# ابزاری قدرتمند برای پرس و جو داده‌ها است";
    
    // تجزیه کلمات
    var words = text.Split(' ', StringSplitOptions.RemoveEmptyEntries);
    
    // پیدا کردن کلمات بلند
    var longWords = words
        .Where(word => word.Length > 4)
        .OrderBy(word => word.Length)
        .ThenBy(word => word)
        .ToList();
    
    Console.WriteLine("کلمات بلند:");
    longWords.ForEach(word => Console.WriteLine($"- {word} ({word.Length} حرف)"));
    
    // شمارش حروف
    var letterCount = text
        .Where(char.IsLetter)
        .GroupBy(c => c)
        .Select(group => new { Letter = group.Key, Count = group.Count() })
        .OrderByDescending(x => x.Count)
        .Take(5);
    
    Console.WriteLine("\n5 حرف پرتکرار:");
    foreach (var item in letterCount)
    {
        Console.WriteLine($"- {item.Letter}: {item.Count} بار");
    }
}

۴۹. Lambda Expressions در C# چیست؟

پاسخ:

Lambda Expressions (عبارات لامبدا) راهی مختصر برای نوشتن توابع کوچک و بی‌نام (Anonymous Functions) هستند. آن‌ها به طور گسترده در LINQ، Event Handling و هر جایی که نیاز به delegate یا expression tree دارید استفاده می‌شوند. Lambda expressions با استفاده از عملگر => (lambda operator) تعریف می‌شوند که به آن "goes to" نیز گفته می‌شود.

ساختار Lambda Expression:
مثال‌های مختلف Lambda:
public static void DemonstrateLambdaBasics()
{
    Console.WriteLine("=== Lambda Expression Examples ===");

    List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    // Lambda با یک پارامتر
    var evenNumbers = numbers.Where(x => x % 2 == 0).ToList();
    Console.WriteLine($"اعداد زوج: {string.Join(", ", evenNumbers)}");

    // Lambda با چند پارامتر
    var pairs = numbers.Select((value, index) => new { Index = index, Value = value, Square = value * value });
    Console.WriteLine("\nجفت‌های ایندکس-مقدار:");
    foreach (var pair in pairs.Take(5))
    {
        Console.WriteLine($"Index: {pair.Index}, Value: {pair.Value}, Square: {pair.Square}");
    }

    // Lambda بدون پارامتر
    Func<string> getMessage = () => $"زمان فعلی: {DateTime.Now:HH:mm:ss}";
    Console.WriteLine($"\n{getMessage()}");

    // Statement Lambda
    Action<int> processNumber = x => 
    {
        if (x % 2 == 0)
            Console.WriteLine($"{x} زوج است");
        else
            Console.WriteLine($"{x} فرد است");
    };

    Console.WriteLine("\nپردازش اعداد:");
    numbers.Take(5).ToList().ForEach(processNumber);
}
مثال با Delegates:
public delegate int MathOperation(int x, int y);
public delegate bool Predicate<T>(T item);

public static void DemonstrateLambdaWithDelegates()
{
    Console.WriteLine("=== Lambda با Delegates ===");

    // استفاده از Lambda با Custom Delegate
    MathOperation add = (x, y) => x + y;
    MathOperation multiply = (x, y) => x * y;
    MathOperation power = (x, y) => (int)Math.Pow(x, y);

    Console.WriteLine($"Add: {add(5, 3)}");       // خروجی: 8
    Console.WriteLine($"Multiply: {multiply(5, 3)}"); // خروجی: 15
    Console.WriteLine($"Power: {power(2, 3)}");   // خروجی: 8

    // استفاده از Func<T>
    Func<int, int, int> subtract = (x, y) => x - y;
    Func<double, double> sqrt = x => Math.Sqrt(x);
    Func<string, int> getLength = str => str?.Length ?? 0;

    Console.WriteLine($"Subtract: {subtract(10, 4)}"); // خروجی: 6
    Console.WriteLine($"Square root of 16: {sqrt(16)}"); // خروجی: 4
    Console.WriteLine($"Length of 'Hello': {getLength("Hello")}"); // خروجی: 5

    // استفاده از Action<T>
    Action<string> printMessage = message => Console.WriteLine($"پیام: {message}");
    Action<int, string> printNumberAndText = (num, text) => Console.WriteLine($"عدد: {num}, متن: {text}");

    printMessage("سلام دنیا!");
    printNumberAndText(42, "جواب نهایی");

    // استفاده از Predicate
    Predicate<int> isEven = x => x % 2 == 0;
    Predicate<string> isLongString = str => str != null && str.Length > 5;

    Console.WriteLine($"Is 4 even? {isEven(4)}"); // True
    Console.WriteLine($"Is 'Hello World' long? {isLongString("Hello World")}"); // True
}
مثال پیشرفته با LINQ:
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string Category { get; set; }
    public int Stock { get; set; }
}

public static void DemonstrateAdvancedLambda()
{
    var products = new List<Product>
    {
        new Product { Id = 1, Name = "لپ‌تاپ", Price = 1500, Category = "الکترونیک", Stock = 10 },
        new Product { Id = 2, Name = "موبایل", Price = 800, Category = "الکترونیک", Stock = 25 },
        new Product { Id = 3, Name = "کتاب", Price = 25, Category = "آموزش", Stock = 100 },
        new Product { Id = 4, Name = "میز", Price = 200, Category = "مبلمان", Stock = 5 },
        new Product { Id = 5, Name = "صندلی", Price = 150, Category = "مبلمان", Stock = 15 }
    };

    Console.WriteLine("=== Lambda پیشرفته با LINQ ===");

    // پیدا کردن محصولات گران
    var expensiveProducts = products
        .Where(p => p.Price > 100)
        .OrderByDescending(p => p.Price)
        .Select(p => new { p.Name, p.Price, p.Category });

    Console.WriteLine("محصولات گران:");
    foreach (var product in expensiveProducts)
    {
        Console.WriteLine($"- {product.Name}: ${product.Price} ({product.Category})");
    }

    // گروه‌بندی و محاسبات
    var categoryStats = products
        .GroupBy(p => p.Category)
        .Select(g => new 
        {
            Category = g.Key,
            Count = g.Count(),
            TotalValue = g.Sum(p => p.Price * p.Stock),
            AveragePrice = g.Average(p => p.Price),
            MaxPrice = g.Max(p => p.Price)
        })
        .OrderByDescending(x => x.TotalValue);

    Console.WriteLine("\nآمار دسته‌بندی:");
    foreach (var stat in categoryStats)
    {
        Console.WriteLine($"- {stat.Category}: {stat.Count} محصول، ارزش کل: ${stat.TotalValue:N0}، میانگین قیمت: ${stat.AveragePrice:F0}");
    }

    // پیدا کردن محصول با شرایط پیچیده
    var bestProduct = products
        .Where(p => p.Stock > 10)
        .OrderByDescending(p => p.Price * p.Stock) // بر اساس ارزش کل موجودی
        .FirstOrDefault();

    if (bestProduct != null)
    {
        Console.WriteLine($"\nبهترین محصول: {bestProduct.Name} (ارزش: ${bestProduct.Price * bestProduct.Stock:N0})");
    }

    // استفاده از Lambda در متدهای مختلف
    bool hasExpensiveElectronics = products.Any(p => p.Category == "الکترونیک" && p.Price > 1000);
    bool allInStock = products.All(p => p.Stock > 0);
    var totalInventoryValue = products.Sum(p => p.Price * p.Stock);

    Console.WriteLine($"\nآیا الکترونیک گران داریم؟ {(hasExpensiveElectronics ? "بله" : "خیر")}");
    Console.WriteLine($"آیا همه محصولات موجود هستند؟ {(allInStock ? "بله" : "خیر")}");
    Console.WriteLine($"ارزش کل موجودی: ${totalInventoryValue:N0}");
}

۵۰. Delegates در C# چیست؟

پاسخ:

Delegates (نمایندگان) نوع داده‌ای هستند که رفرنس به متدها را نگه می‌دارند. آن‌ها مشابه اشاره‌گرهای تابع (Function Pointers) در زبان‌های دیگر هستند، اما type-safe و object-oriented هستند. Delegates امکان فراخوانی غیرمستقیم متدها، پیاده‌سازی callback functions و event handling را فراهم می‌کنند.

انواع Delegates:
مثال تعریف و استفاده از Delegate:
// تعریف delegate types
public delegate void NotificationDelegate(string message);
public delegate int CalculationDelegate(int x, int y);
public delegate bool ValidationDelegate(string input);

public class DelegateExample
{
    // متدهای مختلف برای notification
    public static void EmailNotification(string message)
    {
        Console.WriteLine($"📧 Email: {message}");
    }

    public static void SMSNotification(string message)
    {
        Console.WriteLine($"📱 SMS: {message}");
    }

    public static void PushNotification(string message)
    {
        Console.WriteLine($"🔔 Push: {message}");
    }

    // متدهای محاسباتی
    public static int Add(int x, int y) => x + y;
    public static int Multiply(int x, int y) => x * y;
    public static int Subtract(int x, int y) => x - y;

    // متدهای اعتبارسنجی
    public static bool IsValidEmail(string email) => email.Contains("@") && email.Contains(".");
    public static bool IsValidPhone(string phone) => phone.Length == 11 && phone.All(char.IsDigit);

    public static void DemonstrateDelegates()
    {
        Console.WriteLine("=== Single-cast Delegates ===");
        
        // Single-cast delegate
        NotificationDelegate notify = EmailNotification;
        notify("خوش آمدید!"); // خروجی: 📧 Email: خوش آمدید!

        // تغییر متد
        notify = SMSNotification;
        notify("سفارش شما آماده است!"); // خروجی: 📱 SMS: سفارش شما آماده است!

        Console.WriteLine("\n=== Multicast Delegates ===");
        
        // Multicast delegate
        NotificationDelegate multiNotify = EmailNotification;
        multiNotify += SMSNotification;  // اضافه کردن متد دوم
        multiNotify += PushNotification; // اضافه کردن متد سوم
        
        multiNotify("پیام مهم!"); // هر سه متد فراخوانی می‌شوند

        // حذف یک متد
        multiNotify -= SMSNotification;
        Console.WriteLine("\nبعد از حذف SMS:");
        multiNotify("پیام دوم");

        Console.WriteLine("\n=== Delegates با Return Value ===");
        
        CalculationDelegate calc = Add;
        Console.WriteLine($"Addition: {calc(10, 5)}"); // خروجی: 15

        calc = Multiply;
        Console.WriteLine($"Multiplication: {calc(10, 5)}"); // خروجی: 50

        // Multicast delegate با return value - فقط آخرین مقدار برگردانده می‌شود
        calc += Subtract;
        int result = calc(10, 5); // فقط نتیجه Subtract (5) برگردانده می‌شود
        Console.WriteLine($"Multicast result (last method): {result}");
    }
}
مثال با Generic Delegates:
public static void DemonstrateGenericDelegates()
{
    Console.WriteLine("=== Generic Delegates ===");

    // Func<T> - delegate با return value
    Func<int, int, int> mathOperation = (x, y) => x + y;
    Console.WriteLine($"Func Add: {mathOperation(8, 3)}"); // 11

    mathOperation = (x, y) => x * y;
    Console.WriteLine($"Func Multiply: {mathOperation(8, 3)}"); // 24

    // Func با انواع مختلف
    Func<string, int> getLength = str => str?.Length ?? 0;
    Func<double, double> square = x => x * x;
    Func<DateTime> getCurrentTime = () => DateTime.Now;

    Console.WriteLine($"Length of 'Hello': {getLength("Hello")}");
    Console.WriteLine($"Square of 4.5: {square(4.5)}");
    Console.WriteLine($"Current time: {getCurrentTime():HH:mm:ss}");

    // Action<T> - delegate بدون return value
    Action<string> logger = message => Console.WriteLine($"[LOG] {DateTime.Now:HH:mm:ss} - {message}");
    Action<int, string> processOrder = (orderId, customerName) => 
        Console.WriteLine($"پردازش سفارش #{orderId} برای {customerName}");

    logger("سیستم راه‌اندازی شد");
    processOrder(1001, "احمد محمدی");

    // Predicate<T> - delegate که bool برمی‌گرداند
    Predicate<int> isEven = number => number % 2 == 0;
    Predicate<string> isValidEmail = email => !string.IsNullOrEmpty(email) && email.Contains("@");

    Console.WriteLine($"Is 6 even? {isEven(6)}"); // True
    Console.WriteLine($"Is '[email protected]' valid? {isValidEmail("[email protected]")}"); // True
}
مثال کاربردی - Event System:
public class OrderProcessor
{
    // تعریف delegate برای events
    public delegate void OrderEventHandler(string orderId, decimal amount);
    
    // Events بر اساس delegates
    public event OrderEventHandler OrderPlaced;
    public event OrderEventHandler OrderShipped;
    public event OrderEventHandler OrderDelivered;

    public void ProcessOrder(string orderId, decimal amount)
    {
        Console.WriteLine($"پردازش سفارش {orderId} به مبلغ ${amount}");
        
        // فعال کردن event
        OrderPlaced?.Invoke(orderId, amount);
        
        // شبیه‌سازی پردازش
        Thread.Sleep(1000);
        
        Console.WriteLine($"ارسال سفارش {orderId}");
        OrderShipped?.Invoke(orderId, amount);
        
        Thread.Sleep(1000);
        
        Console.WriteLine($"تحویل سفارش {orderId}");
        OrderDelivered?.Invoke(orderId, amount);
    }
}

public class NotificationService
{
    public void OnOrderPlaced(string orderId, decimal amount)
    {
        Console.WriteLine($"📧 ایمیل تأیید سفارش {orderId} ارسال شد");
    }

    public void OnOrderShipped(string orderId, decimal amount)
    {
        Console.WriteLine($"📱 پیامک حمل و نقل برای سفارش {orderId} ارسال شد");
    }

    public void OnOrderDelivered(string orderId, decimal amount)
    {
        Console.WriteLine($"🎉 پیام تحویل موفق سفارش {orderId} ارسال شد");
    }
}

public class InventoryService
{
    public void OnOrderPlaced(string orderId, decimal amount)
    {
        Console.WriteLine($"📦 موجودی برای سفارش {orderId} کسر شد");
    }
}

public static void DemonstrateEventSystem()
{
    Console.WriteLine("=== Event System با Delegates ===");
    
    OrderProcessor processor = new OrderProcessor();
    NotificationService notifications = new NotificationService();
    InventoryService inventory = new InventoryService();

    // Subscribe کردن به events
    processor.OrderPlaced += notifications.OnOrderPlaced;
    processor.OrderPlaced += inventory.OnOrderPlaced;
    processor.OrderShipped += notifications.OnOrderShipped;
    processor.OrderDelivered += notifications.OnOrderDelivered;

    // پردازش سفارش
    processor.ProcessOrder("ORD-001", 299.99m);
}
بهترین شیوه‌ها:

۵۱. Events در C# چیست و چه تفاوتی با Delegates دارد؟

پاسخ:

Events (رویدادها) مکانیزمی برای اطلاع‌رسانی هستند که بر پایه Delegates ساخته شده‌اند. Event یک نوع خاص از Delegate است که کپسوله‌سازی و کنترل دسترسی بهتری فراهم می‌کند. در حالی که Delegate یک نوع داده است که رفرنس به متدها را نگه می‌دارد، Event یک الگوی طراحی برای پیاده‌سازی Publisher-Subscriber pattern است.

تفاوت‌های اصلی Events و Delegates:
مثال مقایسه Delegate و Event:
// تعریف delegate
public delegate void MessageHandler(string message);

// کلاس با Delegate
public class DelegatePublisher
{
    public MessageHandler OnMessage; // Delegate عمومی

    public void SendMessage(string msg)
    {
        Console.WriteLine("DelegatePublisher: Sending message...");
        OnMessage?.Invoke(msg); // فراخوانی مستقیم Delegate
    }
}

// کلاس با Event
public class EventPublisher
{
    public event MessageHandler OnEventMessage; // Event بر پایه delegate

    public void SendEventMessage(string msg)
    {
        Console.WriteLine("EventPublisher: Sending event message...");
        OnEventMessage?.Invoke(msg); // فراخوانی رویداد
    }

    // متد کمکی برای فعال‌سازی event از خارج (اختیاری)
    public void TriggerEvent(string message)
    {
        OnEventMessage?.Invoke(message);
    }
}

public class Subscriber
{
    private string _name;

    public Subscriber(string name)
    {
        _name = name;
    }

    public void HandleMessage(string message)
    {
        Console.WriteLine($"Subscriber {_name}: Received message: {message}");
    }
}

public static void DemonstrateDelegateVsEvent()
{
    Console.WriteLine("=== Delegate Example ===");
    DelegatePublisher delegatePub = new DelegatePublisher();
    Subscriber sub1 = new Subscriber("Sub1");
    Subscriber sub2 = new Subscriber("Sub2");

    // اضافه کردن مشترکین
    delegatePub.OnMessage += sub1.HandleMessage;
    delegatePub.OnMessage += sub2.HandleMessage;

    delegatePub.SendMessage("Hello from Delegate!");

    // خطر: می‌توان delegate را مستقیماً دستکاری کرد
    delegatePub.OnMessage = null; // تمام مشترکین حذف می‌شوند!
    delegatePub.SendMessage("This won't be received!"); // هیچ خروجی نخواهد داشت

    Console.WriteLine("\n=== Event Example ===");
    EventPublisher eventPub = new EventPublisher();
    Subscriber sub3 = new Subscriber("Sub3");
    Subscriber sub4 = new Subscriber("Sub4");

    // اضافه کردن مشترکین
    eventPub.OnEventMessage += sub3.HandleMessage;
    eventPub.OnEventMessage += sub4.HandleMessage;

    eventPub.SendEventMessage("Hello from Event!");

    // این خط خطای کامپایل می‌دهد:
    // eventPub.OnEventMessage = null; // خطا: The event can only appear on the left hand side of += or -=
    
    // فقط می‌توان مشترک اضافه یا حذف کرد
    eventPub.OnEventMessage -= sub3.HandleMessage;
    eventPub.SendEventMessage("Only Sub4 will receive this!");
}
مثال کاربردی - سیستم سفارش:
public class Order
{
    public string OrderId { get; set; }
    public decimal Amount { get; set; }
    public string CustomerName { get; set; }
}

public class OrderService
{
    // تعریف events مختلف
    public event Action<Order> OrderCreated;
    public event Action<Order> OrderShipped;
    public event Action<Order, string> OrderCancelled;

    public void CreateOrder(string orderId, decimal amount, string customerName)
    {
        var order = new Order 
        { 
            OrderId = orderId, 
            Amount = amount, 
            CustomerName = customerName 
        };

        Console.WriteLine($"Creating order {orderId} for {customerName}");
        
        // فعال‌سازی event
        OrderCreated?.Invoke(order);
    }

    public void ShipOrder(Order order)
    {
        Console.WriteLine($"Shipping order {order.OrderId}");
        OrderShipped?.Invoke(order);
    }

    public void CancelOrder(Order order, string reason)
    {
        Console.WriteLine($"Cancelling order {order.OrderId}: {reason}");
        OrderCancelled?.Invoke(order, reason);
    }
}

// سرویس‌های مختلف که به events گوش می‌دهند
public class EmailService
{
    public void OnOrderCreated(Order order)
    {
        Console.WriteLine($"📧 Sending confirmation email to {order.CustomerName}");
    }

    public void OnOrderShipped(Order order)
    {
        Console.WriteLine($"📧 Sending shipping notification to {order.CustomerName}");
    }

    public void OnOrderCancelled(Order order, string reason)
    {
        Console.WriteLine($"📧 Sending cancellation email to {order.CustomerName}: {reason}");
    }
}

public class InventoryService
{
    public void OnOrderCreated(Order order)
    {
        Console.WriteLine($"📦 Reserving inventory for order {order.OrderId}");
    }

    public void OnOrderCancelled(Order order, string reason)
    {
        Console.WriteLine($"📦 Releasing inventory for order {order.OrderId}");
    }
}

public class LoggingService
{
    public void OnOrderCreated(Order order)
    {
        Console.WriteLine($"📝 Logging: Order {order.OrderId} created - Amount: ${order.Amount}");
    }

    public void OnOrderShipped(Order order)
    {
        Console.WriteLine($"📝 Logging: Order {order.OrderId} shipped");
    }
}

public static void DemonstrateEventSystem()
{
    Console.WriteLine("=== Event-Driven Order System ===");
    
    // ایجاد سرویس‌ها
    OrderService orderService = new OrderService();
    EmailService emailService = new EmailService();
    InventoryService inventoryService = new InventoryService();
    LoggingService loggingService = new LoggingService();

    // Subscribe کردن به events
    orderService.OrderCreated += emailService.OnOrderCreated;
    orderService.OrderCreated += inventoryService.OnOrderCreated;
    orderService.OrderCreated += loggingService.OnOrderCreated;

    orderService.OrderShipped += emailService.OnOrderShipped;
    orderService.OrderShipped += loggingService.OnOrderShipped;

    orderService.OrderCancelled += emailService.OnOrderCancelled;
    orderService.OrderCancelled += inventoryService.OnOrderCancelled;

    // تست سیستم
    orderService.CreateOrder("ORD-001", 299.99m, "احمد محمدی");
    
    Console.WriteLine("\n---");
    var order = new Order { OrderId = "ORD-001", Amount = 299.99m, CustomerName = "احمد محمدی" };
    orderService.ShipOrder(order);
    
    Console.WriteLine("\n---");
    orderService.CancelOrder(order, "Customer requested cancellation");
}
مثال Custom EventArgs:
// تعریف Custom EventArgs
public class OrderEventArgs : EventArgs
{
    public Order Order { get; }
    public DateTime Timestamp { get; }
    public string Source { get; }

    public OrderEventArgs(Order order, string source)
    {
        Order = order;
        Source = source;
        Timestamp = DateTime.Now;
    }
}

public class AdvancedOrderService
{
    // استفاده از EventHandler<T> pattern
    public event EventHandler<OrderEventArgs> OrderProcessed;

    public void ProcessOrder(Order order)
    {
        Console.WriteLine($"Processing order {order.OrderId}");
        
        // فعال‌سازی event با اطلاعات کامل
        OnOrderProcessed(new OrderEventArgs(order, "OrderService"));
    }

    // الگوی استاندارد برای فعال‌سازی events
    protected virtual void OnOrderProcessed(OrderEventArgs e)
    {
        OrderProcessed?.Invoke(this, e);
    }
}

public static void DemonstrateCustomEventArgs()
{
    AdvancedOrderService service = new AdvancedOrderService();
    
    service.OrderProcessed += (sender, e) => 
    {
        Console.WriteLine($"Event received at {e.Timestamp:HH:mm:ss}");
        Console.WriteLine($"Order: {e.Order.OrderId}, Source: {e.Source}");
        Console.WriteLine($"Sender type: {sender.GetType().Name}");
    };

    var order = new Order { OrderId = "ORD-002", Amount = 150.00m, CustomerName = "فاطمه احمدی" };
    service.ProcessOrder(order);
}
بهترین شیوه‌ها:

۵۲. Anonymous Types در C# چیست؟

پاسخ:

Anonymous Types (انواع ناشناس) امکان ایجاد اشیاء بدون تعریف صریح کلاس را فراهم می‌کنند. این انواع در زمان کامپایل به صورت خودکار توسط کامپایلر تولید می‌شوند و معمولاً در LINQ queries و سناریوهایی که نیاز به ایجاد اشیاء موقت دارید استفاده می‌شوند. Anonymous Types فقط خواندنی (read-only) هستند و نمی‌توان آن‌ها را تغییر داد.

ویژگی‌های Anonymous Types:
مثال پایه:
public static void DemonstrateAnonymousTypes()
{
    Console.WriteLine("=== Anonymous Types Examples ===");

    // ایجاد anonymous type ساده
    var person = new { Name = "احمد محمدی", Age = 30, City = "تهران" };
    
    Console.WriteLine($"Person: {person.Name}, {person.Age} years old, from {person.City}");
    Console.WriteLine($"Type name: {person.GetType().Name}");

    // anonymous type با انواع داده مختلف
    var product = new 
    { 
        Id = 1001,
        Name = "لپ‌تاپ",
        Price = 1500.99m,
        InStock = true,
        Categories = new[] { "الکترونیک", "کامپیوتر" },
        LaunchDate = new DateTime(2023, 6, 15)
    };

    Console.WriteLine($"\nProduct: {product.Name}");
    Console.WriteLine($"Price: ${product.Price}, In Stock: {product.InStock}");
    Console.WriteLine($"Categories: {string.Join(", ", product.Categories)}");
    Console.WriteLine($"Launch Date: {product.LaunchDate:yyyy-MM-dd}");

    // آرایه از anonymous types
    var employees = new[]
    {
        new { Id = 1, Name = "علی رضایی", Department = "IT", Salary = 75000 },
        new { Id = 2, Name = "فاطمه احمدی", Department = "HR", Salary = 65000 },
        new { Id = 3, Name = "حسن محمدی", Department = "Finance", Salary = 70000 }
    };

    Console.WriteLine("\nEmployees:");
    foreach (var emp in employees)
    {
        Console.WriteLine($"- {emp.Name} ({emp.Department}): ${emp.Salary:N0}");
    }

    // anonymous type تو در تو
    var order = new
    {
        OrderId = "ORD-001",
        Customer = new { Name = "زهرا احمدی", Email = "[email protected]" },
        Items = new[]
        {
            new { ProductName = "کتاب", Quantity = 2, Price = 25.00m },
            new { ProductName = "قلم", Quantity = 5, Price = 3.50m }
        },
        Total = 67.50m
    };

    Console.WriteLine($"\nOrder {order.OrderId} for {order.Customer.Name}:");
    foreach (var item in order.Items)
    {
        Console.WriteLine($"- {item.ProductName}: {item.Quantity} × ${item.Price} = ${item.Quantity * item.Price}");
    }
    Console.WriteLine($"Total: ${order.Total}");
}
مثال با LINQ:
public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Major { get; set; }
    public double GPA { get; set; }
    public int Age { get; set; }
}

public static void DemonstrateAnonymousTypesWithLinq()
{
    var students = new List<Student>
    {
        new Student { Id = 1, Name = "احمد محمدی", Major = "کامپیوتر", GPA = 3.8, Age = 20 },
        new Student { Id = 2, Name = "فاطمه احمدی", Major = "ریاضی", GPA = 3.9, Age = 22 },
        new Student { Id = 3, Name = "علی رضایی", Major = "کامپیوتر", GPA = 3.5, Age = 19 },
        new Student { Id = 4, Name = "زهرا محمدی", Major = "فیزیک", GPA = 3.7, Age = 21 },
        new Student { Id = 5, Name = "حسن احمدی", Major = "ریاضی", GPA = 3.6, Age = 23 }
    };

    Console.WriteLine("=== Anonymous Types with LINQ ===");

    // انتخاب فیلدهای خاص با anonymous type
    var basicInfo = students
        .Where(s => s.GPA > 3.6)
        .Select(s => new { s.Name, s.GPA, Grade = s.GPA >= 3.8 ? "A" : "B" })
        .OrderByDescending(x => x.GPA);

    Console.WriteLine("Students with GPA > 3.6:");
    foreach (var student in basicInfo)
    {
        Console.WriteLine($"- {student.Name}: GPA {student.GPA} (Grade: {student.Grade})");
    }

    // گروه‌بندی با anonymous type
    var majorStats = students
        .GroupBy(s => s.Major)
        .Select(g => new 
        { 
            Major = g.Key,
            Count = g.Count(),
            AverageGPA = g.Average(s => s.GPA),
            AverageAge = g.Average(s => s.Age),
            TopStudent = g.OrderByDescending(s => s.GPA).First().Name
        });

    Console.WriteLine("\nMajor Statistics:");
    foreach (var stat in majorStats)
    {
        Console.WriteLine($"- {stat.Major}:");
        Console.WriteLine($"  Count: {stat.Count}, Avg GPA: {stat.AverageGPA:F2}");
        Console.WriteLine($"  Avg Age: {stat.AverageAge:F1}, Top Student: {stat.TopStudent}");
    }

    // Join با anonymous type
    var courses = new[]
    {
        new { CourseId = 1, CourseName = "ریاضی پیشرفته", MajorRequired = "ریاضی" },
        new { CourseId = 2, CourseName = "برنامه‌نویسی", MajorRequired = "کامپیوتر" },
        new { CourseId = 3, CourseName = "فیزیک کوانتوم", MajorRequired = "فیزیک" }
    };

    var eligibleStudents = from student in students
                          join course in courses on student.Major equals course.MajorRequired
                          where student.GPA >= 3.5
                          select new 
                          { 
                              StudentName = student.Name,
                              StudentGPA = student.GPA,
                              CourseName = course.CourseName,
                              Eligibility = student.GPA >= 3.8 ? "Highly Qualified" : "Qualified"
                          };

    Console.WriteLine("\nEligible Students for Advanced Courses:");
    foreach (var item in eligibleStudents)
    {
        Console.WriteLine($"- {item.StudentName} (GPA: {item.StudentGPA}) → {item.CourseName} ({item.Eligibility})");
    }
}
مثال Comparison و Equality:
public static void DemonstrateAnonymousTypeEquality()
{
    Console.WriteLine("=== Anonymous Type Equality ===");

    // دو anonymous type با ساختار یکسان
    var person1 = new { Name = "احمد", Age = 25 };
    var person2 = new { Name = "احمد", Age = 25 };
    var person3 = new { Name = "فاطمه", Age = 25 };

    // مقایسه equality
    Console.WriteLine($"person1.Equals(person2): {person1.Equals(person2)}"); // True
    Console.WriteLine($"person1.Equals(person3): {person1.Equals(person3)}"); // False
    Console.WriteLine($"person1 == person2: {person1 == person2}"); // False (reference equality)

    // ToString() override شده
    Console.WriteLine($"person1.ToString(): {person1.ToString()}");
    Console.WriteLine($"person2.ToString(): {person2.ToString()}");

    // GetHashCode() override شده
    Console.WriteLine($"person1.GetHashCode(): {person1.GetHashCode()}");
    Console.WriteLine($"person2.GetHashCode(): {person2.GetHashCode()}");

    // استفاده در Dictionary
    var personCounts = new Dictionary<object, int>();
    personCounts[person1] = 1;
    personCounts[person2] = 2; // person1 را override می‌کند چون Equals true است

    Console.WriteLine($"Dictionary count: {personCounts.Count}"); // 1
    Console.WriteLine($"Value for person1: {personCounts[person1]}"); // 2
}
محدودیت‌ها و نکات:

۵۳. var keyword در C# چیست؟

پاسخ:

var keyword امکان تعریف متغیرهای محلی با استنباط نوع خودکار (Implicit Type Inference) را فراهم می‌کند. هنگام استفاده از var، کامپایلر نوع متغیر را بر اساس مقدار اولیه‌ای که به آن انتساب می‌دهید، تشخیص می‌دهد. این کلمه کلیدی فقط برای متغیرهای محلی (local variables) قابل استفاده است و باید حتماً در زمان تعریف مقداردهی اولیه شود.

ویژگی‌های var keyword:
مثال‌های پایه:
public static void DemonstrateVarKeyword()
{
    Console.WriteLine("=== var Keyword Examples ===");

    // استنباط نوع‌های ساده
    var number = 42;           // int
    var price = 19.99m;        // decimal
    var name = "احمد محمدی";    // string
    var isActive = true;       // bool
    var today = DateTime.Now;  // DateTime

    Console.WriteLine($"number: {number} (Type: {number.GetType().Name})");
    Console.WriteLine($"price: {price} (Type: {price.GetType().Name})");
    Console.WriteLine($"name: {name} (Type: {name.GetType().Name})");
    Console.WriteLine($"isActive: {isActive} (Type: {isActive.GetType().Name})");
    Console.WriteLine($"today: {today} (Type: {today.GetType().Name})");

    // استنباط نوع‌های پیچیده
    var numbers = new List<int> { 1, 2, 3, 4, 5 };
    var dictionary = new Dictionary<string, int> 
    { 
        ["apple"] = 5, 
        ["banana"] = 3 
    };
    var array = new[] { "red", "green", "blue" };

    Console.WriteLine($"\nnumbers type: {numbers.GetType().Name}<{numbers.GetType().GetGenericArguments()[0].Name}>");
    Console.WriteLine($"dictionary type: {dictionary.GetType().Name}");
    Console.WriteLine($"array type: {array.GetType().Name}");

    // var با anonymous types
    var person = new { Name = "فاطمه احمدی", Age = 28, Department = "IT" };
    Console.WriteLine($"\nAnonymous type: {person.Name}, {person.Age}, {person.Department}");
    Console.WriteLine($"Type: {person.GetType().Name}");

    // var با LINQ
    var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();
    var firstEven = numbers.FirstOrDefault(n => n % 2 == 0);
    
    Console.WriteLine($"\nevenNumbers: [{string.Join(", ", evenNumbers)}]");
    Console.WriteLine($"firstEven: {firstEven} (Type: {firstEven.GetType().Name})");
}
مثال با LINQ و Anonymous Types:
public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Department { get; set; }
    public decimal Salary { get; set; }
    public DateTime HireDate { get; set; }
}

public static void DemonstrateVarWithLinq()
{
    var employees = new List<Employee>
    {
        new Employee { Id = 1, Name = "احمد محمدی", Department = "IT", Salary = 75000, HireDate = new DateTime(2020, 1, 15) },
        new Employee { Id = 2, Name = "فاطمه احمدی", Department = "HR", Salary = 65000, HireDate = new DateTime(2019, 3, 10) },
        new Employee { Id = 3, Name = "علی رضایی", Department = "IT", Salary = 80000, HireDate = new DateTime(2021, 6, 20) },
        new Employee { Id = 4, Name = "زهرا محمدی", Department = "Finance", Salary = 70000, HireDate = new DateTime(2018, 9, 5) }
    };

    Console.WriteLine("=== var with LINQ Examples ===");

    // var با LINQ query syntax
    var highSalaryEmployees = from emp in employees
                             where emp.Salary > 70000
                             orderby emp.Salary descending
                             select new 
                             { 
                                 emp.Name, 
                                 emp.Department, 
                                 emp.Salary,
                                 YearsOfService = DateTime.Now.Year - emp.HireDate.Year
                             };

    Console.WriteLine("High Salary Employees:");
    foreach (var emp in highSalaryEmployees)
    {
        Console.WriteLine($"- {emp.Name} ({emp.Department}): ${emp.Salary:N0}, {emp.YearsOfService} years");
    }

    // var با method syntax
    var departmentStats = employees
        .GroupBy(e => e.Department)
        .Select(g => new 
        {
            Department = g.Key,
            Count = g.Count(),
            AverageSalary = g.Average(e => e.Salary),
            TotalSalary = g.Sum(e => e.Salary),
            NewestHire = g.Max(e => e.HireDate)
        })
        .OrderByDescending(x => x.AverageSalary);

    Console.WriteLine("\nDepartment Statistics:");
    foreach (var stat in departmentStats)
    {
        Console.WriteLine($"- {stat.Department}:");
        Console.WriteLine($"  Employees: {stat.Count}");
        Console.WriteLine($"  Average Salary: ${stat.AverageSalary:N0}");
        Console.WriteLine($"  Total Salary: ${stat.TotalSalary:N0}");
        Console.WriteLine($"  Newest Hire: {stat.NewestHire:yyyy-MM-dd}");
    }

    // var با complex LINQ operations
    var complexQuery = employees
        .Where(e => e.HireDate.Year >= 2019)
        .GroupBy(e => new { e.Department, Year = e.HireDate.Year })
        .Select(g => new
        {
            g.Key.Department,
            g.Key.Year,
            Employees = g.Select(e => new { e.Name, e.Salary }).ToList(),
            Count = g.Count(),
            AverageSalary = g.Average(e => e.Salary)
        })
        .OrderBy(x => x.Department)
        .ThenBy(x => x.Year);

    Console.WriteLine("\nComplex Query Results:");
    foreach (var item in complexQuery)
    {
        Console.WriteLine($"- {item.Department} ({item.Year}): {item.Count} employees, Avg: ${item.AverageSalary:N0}");
        foreach (var emp in item.Employees)
        {
            Console.WriteLine($"  • {emp.Name}: ${emp.Salary:N0}");
        }
    }
}
مثال بهترین شیوه‌ها و محدودیت‌ها:
public static void DemonstrateVarBestPractices()
{
    Console.WriteLine("=== var Best Practices and Limitations ===");

    // ✅ خوب: نوع واضح از context
    var customers = new List<string>();
    var connectionString = "Server=localhost;Database=MyDB;";
    var startTime = DateTime.Now;

    // ✅ خوب: LINQ و anonymous types
    var result = customers.Select(c => new { Name = c, Length = c.Length });

    // ✅ خوب: نوع‌های پیچیده و طولانی
    var dictionary = new Dictionary<string, List<int>>();

    // ⚠️ قابل بحث: نوع از نام متغیر واضح نیست
    var data = GetData(); // نوع return مشخص نیست
    var value = CalculateValue(); // نوع return مشخص نیست

    // ❌ بد: نوع‌های ساده که واضح هستند
    // بهتر است explicit باشند برای خوانایی
    int count = 10;        // بهتر از: var count = 10;
    string message = "Hi"; // بهتر از: var message = "Hi";
    bool isValid = true;   // بهتر از: var isValid = true;

    // محدودیت‌ها:
    
    // ❌ نمی‌توان بدون مقداردهی اولیه استفاده کرد
    // var uninitializedVar; // خطای کامپایل

    // ❌ نمی‌توان null انتساب داد
    // var nullVar = null; // خطای کامپایل

    // ❌ نمی‌توان برای فیلدهای کلاس استفاده کرد
    // public var ClassField = 10; // خطای کامپایل

    // ❌ نمی‌توان برای پارامترهای متد استفاده کرد
    // public void Method(var parameter) { } // خطای کامپایل

    // ✅ راه حل برای null: استفاده از explicit type
    string nullableString = null;
    int? nullableInt = null;

    Console.WriteLine("var keyword demonstration completed!");
}

// متدهای کمکی
private static object GetData()
{
    return new { Id = 1, Name = "Test" };
}

private static decimal CalculateValue()
{
    return 123.45m;
}
مثال مقایسه var vs explicit typing:
public static void CompareVarVsExplicitTyping()
{
    Console.WriteLine("=== var vs Explicit Typing Comparison ===");

    // Scenario 1: Collections
    var listVar = new List<string>(); // واضح و مختصر
    List<string> listExplicit = new List<string>(); // تکراری اما واضح

    // Scenario 2: LINQ Results
    var employees = GetEmployees();
    
    // با var - مختصر و خوانا
    var queryVar = employees
        .Where(e => e.Salary > 50000)
        .Select(e => new { e.Name, e.Salary });

    // بدون var - طولانی و پیچیده
    IEnumerable<object> queryExplicit = employees
        .Where(e => e.Salary > 50000)
        .Select(e => new { e.Name, e.Salary });

    // Scenario 3: Dictionary with complex types
    var complexDict = new Dictionary<string, List<Tuple<int, string>>>();
    Dictionary<string, List<Tuple<int, string>>> explicitDict = 
        new Dictionary<string, List<Tuple<int, string>>>();

    Console.WriteLine("Comparison completed - var provides cleaner, more readable code in many scenarios!");
}

private static List<Employee> GetEmployees()
{
    return new List<Employee>
    {
        new Employee { Name = "احمد", Salary = 60000 },
        new Employee { Name = "فاطمه", Salary = 75000 }
    };
}
بهترین شیوه‌ها:

۵۴. dynamic keyword در C# چیست؟

پاسخ:

dynamic keyword امکان تعریف متغیرهایی را فراهم می‌کند که نوع آن‌ها در زمان اجرا (runtime) تعیین می‌شود، نه در زمان کامپایل. برخلاف var که در compile time نوع را تشخیص می‌دهد، dynamic تمام type checking را به runtime موکول می‌کند. این ویژگی برای کار با COM objects، reflection، و سناریوهایی که نوع داده از قبل مشخص نیست بسیار مفید است.

ویژگی‌های dynamic keyword:
مثال‌های پایه:
public static void DemonstrateDynamicBasics()
{
    Console.WriteLine("=== dynamic Keyword Basics ===");

    // تعریف متغیر dynamic
    dynamic value = 42;
    Console.WriteLine($"value = {value}, Type: {value.GetType().Name}");

    // تغییر نوع در runtime
    value = "Hello World";
    Console.WriteLine($"value = {value}, Type: {value.GetType().Name}");

    value = DateTime.Now;
    Console.WriteLine($"value = {value}, Type: {value.GetType().Name}");

    value = new List<int> { 1, 2, 3, 4, 5 };
    Console.WriteLine($"value Count = {value.Count}, Type: {value.GetType().Name}");

    // عملیات‌های مختلف بر روی dynamic
    dynamic num1 = 10;
    dynamic num2 = 20;
    dynamic result = num1 + num2; // جمع اعداد
    Console.WriteLine($"Numeric addition: {num1} + {num2} = {result}");

    dynamic str1 = "Hello ";
    dynamic str2 = "World";
    result = str1 + str2; // الحاق رشته‌ها
    Console.WriteLine($"String concatenation: '{str1}' + '{str2}' = '{result}'");

    // فراخوانی متدها
    dynamic text = "dynamic programming";
    result = text.ToUpper(); // فراخوانی متد string
    Console.WriteLine($"ToUpper(): {result}");

    // دسترسی به propertyها
    dynamic person = new { Name = "احمد محمدی", Age = 30 };
    Console.WriteLine($"Person: {person.Name}, Age: {person.Age}");
}
مثال با ExpandoObject:
using System.Dynamic;

public static void DemonstrateExpandoObject()
{
    Console.WriteLine("=== ExpandoObject with dynamic ===");

    // ایجاد شیء پویا با ExpandoObject
    dynamic expando = new ExpandoObject();
    
    // اضافه کردن propertyها در runtime
    expando.Name = "فاطمه احمدی";
    expando.Age = 28;
    expando.Department = "IT";
    expando.IsActive = true;

    Console.WriteLine($"Employee: {expando.Name}, Age: {expando.Age}");
    Console.WriteLine($"Department: {expando.Department}, Active: {expando.IsActive}");

    // اضافه کردن متد در runtime
    expando.GetInfo = new Func<string>(() => 
        $"{expando.Name} works in {expando.Department} department");

    Console.WriteLine($"Info: {expando.GetInfo()}");

    // تبدیل به Dictionary برای دسترسی به کلیدها
    var expandoDict = (IDictionary<string, object>)expando;
    Console.WriteLine("\nProperties:");
    foreach (var kvp in expandoDict)
    {
        if (!(kvp.Value is Delegate)) // فقط propertyها، نه متدها
        {
            Console.WriteLine($"- {kvp.Key}: {kvp.Value}");
        }
    }

    // حذف property
    expandoDict.Remove("IsActive");
    Console.WriteLine($"\nAfter removing IsActive, Keys count: {expandoDict.Keys.Count}");

    // اضافه کردن property جدید
    expando.Salary = 75000;
    expando.HireDate = DateTime.Now.AddYears(-2);
    
    Console.WriteLine($"Salary: ${expando.Salary:N0}");
    Console.WriteLine($"Hire Date: {expando.HireDate:yyyy-MM-dd}");
}
مثال کاربردی - JSON Processing:
// شبیه‌سازی JSON processing بدون external library
public static void DemonstrateDynamicJsonProcessing()
{
    Console.WriteLine("=== Dynamic JSON-like Processing ===");

    // شبیه‌سازی JSON object
    dynamic jsonData = new ExpandoObject();
    jsonData.id = 1001;
    jsonData.name = "محصول نمونه";
    jsonData.price = 299.99;
    jsonData.inStock = true;
    jsonData.categories = new[] { "الکترونیک", "کامپیوتر" };
    
    // nested object
    jsonData.supplier = new ExpandoObject();
    jsonData.supplier.name = "شرکت ABC";
    jsonData.supplier.country = "ایران";
    jsonData.supplier.rating = 4.5;

    // پردازش داده‌های JSON-like
    Console.WriteLine($"Product: {jsonData.name} (ID: {jsonData.id})");
    Console.WriteLine($"Price: ${jsonData.price}, In Stock: {jsonData.inStock}");
    Console.WriteLine($"Categories: {string.Join(", ", jsonData.categories)}");
    Console.WriteLine($"Supplier: {jsonData.supplier.name} from {jsonData.supplier.country}");
    Console.WriteLine($"Supplier Rating: {jsonData.supplier.rating}/5");

    // پردازش پویا بر اساس وجود propertyها
    var dataDict = (IDictionary<string, object>)jsonData;
    
    if (dataDict.ContainsKey("discount"))
    {
        Console.WriteLine($"Discount: {jsonData.discount}%");
    }
    else
    {
        Console.WriteLine("No discount available");
    }

    // اضافه کردن property جدید
    jsonData.lastUpdated = DateTime.Now;
    jsonData.version = "1.0";

    Console.WriteLine($"Last Updated: {jsonData.lastUpdated:yyyy-MM-dd HH:mm:ss}");
    Console.WriteLine($"Version: {jsonData.version}");
}
مثال Exception Handling:
public static void DemonstrateDynamicExceptionHandling()
{
    Console.WriteLine("=== Dynamic Exception Handling ===");

    dynamic obj = "Hello World";

    try
    {
        // عملیات معتبر
        int length = obj.Length;
        Console.WriteLine($"String length: {length}");

        string upper = obj.ToUpper();
        Console.WriteLine($"Uppercase: {upper}");

        // عملیات نامعتبر - متد وجود ندارد
        obj.NonExistentMethod();
    }
    catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
    {
        Console.WriteLine($"Runtime binding error: {ex.Message}");
    }

    try
    {
        // تغییر نوع
        obj = 42;
        Console.WriteLine($"Number: {obj}");

        // تلاش برای فراخوانی متد string روی int
        string result = obj.ToUpper(); // خطا!
    }
    catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
    {
        Console.WriteLine($"Runtime binding error: {ex.Message}");
    }

    try
    {
        // عملیات ریاضی نامعتبر
        obj = "not a number";
        int calculation = obj + 10; // خطا!
    }
    catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
    {
        Console.WriteLine($"Runtime binding error: {ex.Message}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Other error: {ex.Message}");
    }
}
مثال مقایسه dynamic vs var vs object:
public static void CompareDynamicVarObject()
{
    Console.WriteLine("=== Comparison: dynamic vs var vs object ===");

    // var - compile-time type inference
    var varValue = "Hello";
    // varValue = 42; // خطای کامپایل - نوع string تعیین شده
    Console.WriteLine($"var: {varValue} (Type: {varValue.GetType().Name})");

    // object - compile-time type checking, runtime casting needed
    object objValue = "Hello";
    objValue = 42; // OK - هر چیزی می‌تواند object باشد
    // int length = objValue.Length; // خطای کامپایل - نیاز به casting
    
    if (objValue is string str)
    {
        int length = str.Length; // OK با pattern matching
        Console.WriteLine($"object (as string): {str}, Length: {length}");
    }
    else if (objValue is int num)
    {
        Console.WriteLine($"object (as int): {num}");
    }

    // dynamic - runtime type checking
    dynamic dynValue = "Hello";
    int dynLength = dynValue.Length; // OK - بررسی در runtime
    Console.WriteLine($"dynamic (as string): {dynValue}, Length: {dynLength}");

    dynValue = 42;
    Console.WriteLine($"dynamic (as int): {dynValue}");
    
    try
    {
        int invalidLength = dynValue.Length; // خطای runtime
    }
    catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException)
    {
        Console.WriteLine("dynamic: Cannot access Length property on int");
    }

    // Performance comparison (conceptual)
    Console.WriteLine("\nPerformance characteristics:");
    Console.WriteLine("- var: Best performance (compile-time resolved)");
    Console.WriteLine("- object: Good performance (with proper casting)");
    Console.WriteLine("- dynamic: Slower performance (runtime resolution)");
}
کاربردهای مناسب dynamic:

۵۵. Reflection در C# چیست و چه کاربردی دارد؟

پاسخ:

Reflection (بازتاب) قابلیتی است که به برنامه اجازه می‌دهد تا اطلاعات مربوط به انواع (Types)، متدها، propertyها و سایر اعضا را در زمان اجرا بررسی کند. این به معنای "خود-بازرسی" کد است. Reflection امکان ایجاد شیء، فراخوانی متدها و دسترسی به propertyها بدون داشتن اطلاعات compile-time را فراهم می‌کند. این ویژگی برای فریم‌ورک‌ها، ORMها، Dependency Injection و سناریوهای پویا بسیار مفید است.

کاربردهای اصلی Reflection:
مثال پایه - Type Inspection:
using System;
using System.Reflection;

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    private string email;
    
    public Person() { }
    
    public Person(int id, string name)
    {
        Id = id;
        Name = name;
    }
    
    public void DisplayInfo()
    {
        Console.WriteLine($"Person: {Name} (ID: {Id})");
    }
    
    private void SetEmail(string emailAddress)
    {
        email = emailAddress;
    }
    
    public string GetEmail() => email;
}

public static void DemonstrateBasicReflection()
{
    Console.WriteLine("=== Basic Reflection Examples ===");
    
    // گرفتن Type information
    Type personType = typeof(Person);
    Console.WriteLine($"Type Name: {personType.Name}");
    Console.WriteLine($"Full Name: {personType.FullName}");
    Console.WriteLine($"Assembly: {personType.Assembly.GetName().Name}");
    Console.WriteLine($"Is Class: {personType.IsClass}");
    Console.WriteLine($"Is Public: {personType.IsPublic}");
    
    // بررسی Constructors
    Console.WriteLine("\nConstructors:");
    ConstructorInfo[] constructors = personType.GetConstructors();
    foreach (ConstructorInfo constructor in constructors)
    {
        ParameterInfo[] parameters = constructor.GetParameters();
        string paramList = string.Join(", ", parameters.Select(p => $"{p.ParameterType.Name} {p.Name}"));
        Console.WriteLine($"- Constructor({paramList})");
    }
    
    // بررسی Properties
    Console.WriteLine("\nProperties:");
    PropertyInfo[] properties = personType.GetProperties();
    foreach (PropertyInfo property in properties)
    {
        Console.WriteLine($"- {property.PropertyType.Name} {property.Name} " +
                         $"(CanRead: {property.CanRead}, CanWrite: {property.CanWrite})");
    }
    
    // بررسی Methods (فقط public)
    Console.WriteLine("\nPublic Methods:");
    MethodInfo[] methods = personType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
    foreach (MethodInfo method in methods)
    {
        if (!method.IsSpecialName) // حذف property getters/setters
        {
            ParameterInfo[] parameters = method.GetParameters();
            string paramList = string.Join(", ", parameters.Select(p => $"{p.ParameterType.Name} {p.Name}"));
            Console.WriteLine($"- {method.ReturnType.Name} {method.Name}({paramList})");
        }
    }
    
    // بررسی Private Methods
    Console.WriteLine("\nPrivate Methods:");
    MethodInfo[] privateMethods = personType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
    foreach (MethodInfo method in privateMethods)
    {
        if (!method.IsSpecialName)
        {
            Console.WriteLine($"- {method.ReturnType.Name} {method.Name}");
        }
    }
}
مثال Dynamic Object Creation و Method Invocation:
public static void DemonstrateDynamicOperations()
{
    Console.WriteLine("=== Dynamic Object Creation and Method Invocation ===");
    
    Type personType = typeof(Person);
    
    // ایجاد شیء با constructor پیش‌فرض
    object personInstance1 = Activator.CreateInstance(personType);
    Console.WriteLine($"Created instance: {personInstance1.GetType().Name}");
    
    // ایجاد شیء با constructor پارامتردار
    object personInstance2 = Activator.CreateInstance(personType, 1, "احمد محمدی");
    
    // دسترسی به Properties
    PropertyInfo nameProperty = personType.GetProperty("Name");
    PropertyInfo idProperty = personType.GetProperty("Id");
    
    // خواندن مقادیر properties
    string name = (string)nameProperty.GetValue(personInstance2);
    int id = (int)idProperty.GetValue(personInstance2);
    Console.WriteLine($"Retrieved values - ID: {id}, Name: {name}");
    
    // تنظیم مقادیر properties
    nameProperty.SetValue(personInstance1, "فاطمه احمدی");
    idProperty.SetValue(personInstance1, 2);
    
    // فراخوانی متد public
    MethodInfo displayMethod = personType.GetMethod("DisplayInfo");
    Console.WriteLine("Calling DisplayInfo on instance1:");
    displayMethod.Invoke(personInstance1, null);
    
    Console.WriteLine("Calling DisplayInfo on instance2:");
    displayMethod.Invoke(personInstance2, null);
    
    // فراخوانی متد private
    MethodInfo setEmailMethod = personType.GetMethod("SetEmail", BindingFlags.NonPublic | BindingFlags.Instance);
    setEmailMethod.Invoke(personInstance1, new object[] { "[email protected]" });
    
    // فراخوانی متد برای گرفتن email
    MethodInfo getEmailMethod = personType.GetMethod("GetEmail");
    string email = (string)getEmailMethod.Invoke(personInstance1, null);
    Console.WriteLine($"Retrieved email: {email}");
}
مثال کاربردی - Generic Factory Pattern:
// Generic Factory با استفاده از Reflection
public class ReflectionFactory
{
    private static Dictionary<string, Type> _typeCache = new Dictionary<string, Type>();
    
    public static T Create<T>(string typeName, params object[] constructorArgs)
    {
        Type type = GetTypeByName(typeName);
        if (type == null || !typeof(T).IsAssignableFrom(type))
        {
            throw new ArgumentException($"Type '{typeName}' not found or not assignable to {typeof(T).Name}");
        }
        
        return (T)Activator.CreateInstance(type, constructorArgs);
    }
    
    public static object Create(string typeName, params object[] constructorArgs)
    {
        Type type = GetTypeByName(typeName);
        if (type == null)
        {
            throw new ArgumentException($"Type '{typeName}' not found");
        }
        
        return Activator.CreateInstance(type, constructorArgs);
    }
    
    private static Type GetTypeByName(string typeName)
    {
        if (_typeCache.ContainsKey(typeName))
        {
            return _typeCache[typeName];
        }
        
        // جستجو در assembly فعلی
        Type type = Type.GetType(typeName);
        if (type == null)
        {
            // جستجو در تمام loaded assemblies
            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                type = assembly.GetType(typeName);
                if (type != null) break;
            }
        }
        
        if (type != null)
        {
            _typeCache[typeName] = type;
        }
        
        return type;
    }
    
    public static List<Type> GetTypesImplementing<T>()
    {
        Type interfaceType = typeof(T);
        List<Type> implementingTypes = new List<Type>();
        
        foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            try
            {
                Type[] types = assembly.GetTypes();
                foreach (Type type in types)
                {
                    if (interfaceType.IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract)
                    {
                        implementingTypes.Add(type);
                    }
                }
            }
            catch (ReflectionTypeLoadException)
            {
                // برخی assemblies ممکن است قابل load نباشند
                continue;
            }
        }
        
        return implementingTypes;
    }
}

// مثال استفاده از Factory
public interface IProcessor
{
    void Process(string data);
}

public class TextProcessor : IProcessor
{
    public string Name { get; set; }
    
    public TextProcessor() { Name = "Default Text Processor"; }
    public TextProcessor(string name) { Name = name; }
    
    public void Process(string data)
    {
        Console.WriteLine($"{Name}: Processing text data: {data}");
    }
}

public class DataProcessor : IProcessor
{
    public void Process(string data)
    {
        Console.WriteLine($"DataProcessor: Processing data: {data}");
    }
}

public static void DemonstrateReflectionFactory()
{
    Console.WriteLine("=== Reflection Factory Pattern ===");
    
    try
    {
        // ایجاد اشیاء با نام type
        var textProcessor1 = ReflectionFactory.Create<IProcessor>("TextProcessor");
        textProcessor1.Process("Hello World");
        
        var textProcessor2 = ReflectionFactory.Create<IProcessor>("TextProcessor", "Custom Text Processor");
        textProcessor2.Process("Custom Processing");
        
        var dataProcessor = ReflectionFactory.Create<IProcessor>("DataProcessor");
        dataProcessor.Process("Data123");
        
        // پیدا کردن تمام پیاده‌سازی‌های یک interface
        Console.WriteLine("\nAll IProcessor implementations:");
        var processorTypes = ReflectionFactory.GetTypesImplementing<IProcessor>();
        foreach (Type type in processorTypes)
        {
            Console.WriteLine($"- {type.Name} in {type.Assembly.GetName().Name}");
        }
        
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Factory error: {ex.Message}");
    }
}
مزایا و معایب Reflection:

۵۶. Attributes در C# چیست و چه کاربردی دارند؟

پاسخ:

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

کاربردهای اصلی Attributes:
مثال Built-in Attributes:
using System;
using System.ComponentModel.DataAnnotations;
using System.Xml.Serialization;

// استفاده از Obsolete attribute
public class LegacyClass
{
    [Obsolete("این متد منسوخ شده است. از NewMethod استفاده کنید.")]
    public void OldMethod()
    {
        Console.WriteLine("Old method called");
    }

    [Obsolete("این متد منسوخ شده و در نسخه بعدی حذف خواهد شد.", true)]
    public void VeryOldMethod()
    {
        Console.WriteLine("Very old method - will cause compile error");
    }

    public void NewMethod()
    {
        Console.WriteLine("New method called");
    }
}

// استفاده از Serialization attributes
[Serializable]
public class Person
{
    [XmlElement("PersonName")]
    public string Name { get; set; }

    [XmlIgnore]
    public string Password { get; set; }

    [XmlAttribute("ID")]
    public int Id { get; set; }

    [NonSerialized]
    private string tempData = "temporary";

    public Person() { }

    public Person(int id, string name)
    {
        Id = id;
        Name = name;
    }
}

// استفاده از Validation attributes
public class User
{
    [Required(ErrorMessage = "نام کاربری الزامی است")]
    [StringLength(50, MinimumLength = 3, ErrorMessage = "نام کاربری باید بین 3 تا 50 کاراکتر باشد")]
    public string Username { get; set; }

    [Required(ErrorMessage = "ایمیل الزامی است")]
    [EmailAddress(ErrorMessage = "فرمت ایمیل صحیح نیست")]
    public string Email { get; set; }

    [Range(18, 100, ErrorMessage = "سن باید بین 18 تا 100 سال باشد")]
    public int Age { get; set; }

    [Phone(ErrorMessage = "شماره تلفن صحیح نیست")]
    public string PhoneNumber { get; set; }

    [Url(ErrorMessage = "آدرس وب‌سایت صحیح نیست")]
    public string Website { get; set; }
}

public static void DemonstrateBuiltInAttributes()
{
    Console.WriteLine("=== Built-in Attributes Demo ===");

    // تست Obsolete attribute
    var legacy = new LegacyClass();
    legacy.OldMethod(); // Warning خواهد داد
    legacy.NewMethod();

    // تست Serialization
    var person = new Person(1, "احمد محمدی") { Password = "secret123" };
    Console.WriteLine($"Person created: {person.Name} (ID: {person.Id})");

    // تست Validation (نیاز به validation framework دارد)
    var user = new User
    {
        Username = "ab", // خطا: کمتر از 3 کاراکتر
        Email = "invalid-email", // خطا: فرمت ایمیل
        Age = 15, // خطا: کمتر از 18
        PhoneNumber = "123", // خطا: فرمت تلفن
        Website = "not-a-url" // خطا: فرمت URL
    };

    Console.WriteLine("User object created with validation attributes");
}
مثال Custom Attribute:
// تعریف Custom Attribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class AuthorAttribute : Attribute
{
    public string Name { get; }
    public string Email { get; set; }
    public string Version { get; set; }
    public DateTime CreatedDate { get; set; }

    public AuthorAttribute(string name)
    {
        Name = name;
        CreatedDate = DateTime.Now;
    }

    public override string ToString()
    {
        return $"Author: {Name}, Email: {Email}, Version: {Version}, Created: {CreatedDate:yyyy-MM-dd}";
    }
}

// Custom Attribute برای Performance Monitoring
[AttributeUsage(AttributeTargets.Method)]
public class PerformanceMonitorAttribute : Attribute
{
    public bool LogExecution { get; set; } = true;
    public bool MeasureTime { get; set; } = true;
    public string Category { get; set; } = "General";

    public PerformanceMonitorAttribute() { }

    public PerformanceMonitorAttribute(string category)
    {
        Category = category;
    }
}

// استفاده از Custom Attributes
[Author("احمد محمدی", Email = "[email protected]", Version = "1.0")]
[Author("فاطمه احمدی", Email = "[email protected]", Version = "1.1")]
public class Calculator
{
    [PerformanceMonitor("Math Operations")]
    public int Add(int a, int b)
    {
        System.Threading.Thread.Sleep(100); // شبیه‌سازی عملیات زمان‌بر
        return a + b;
    }

    [PerformanceMonitor("Math Operations", LogExecution = false)]
    public int Multiply(int a, int b)
    {
        System.Threading.Thread.Sleep(50);
        return a * b;
    }

    [Author("علی رضایی", Email = "[email protected]")]
    [PerformanceMonitor("Advanced Math", MeasureTime = true)]
    public double CalculateSquareRoot(double number)
    {
        if (number < 0)
            throw new ArgumentException("عدد نمی‌تواند منفی باشد");
        
        return Math.Sqrt(number);
    }
}

public static void DemonstrateCustomAttributes()
{
    Console.WriteLine("=== Custom Attributes Demo ===");

    Type calculatorType = typeof(Calculator);

    // خواندن Class-level attributes
    Console.WriteLine("Class Authors:");
    var classAuthors = calculatorType.GetCustomAttributes(typeof(AuthorAttribute), false);
    foreach (AuthorAttribute author in classAuthors)
    {
        Console.WriteLine($"- {author}");
    }

    // خواندن Method-level attributes
    Console.WriteLine("\nMethod Information:");
    var methods = calculatorType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

    foreach (var method in methods)
    {
        Console.WriteLine($"\nMethod: {method.Name}");

        // بررسی Author attributes
        var methodAuthors = method.GetCustomAttributes(typeof(AuthorAttribute), false);
        foreach (AuthorAttribute author in methodAuthors)
        {
            Console.WriteLine($"  Author: {author.Name} ({author.Email})");
        }

        // بررسی Performance Monitor attributes
        var perfMonitors = method.GetCustomAttributes(typeof(PerformanceMonitorAttribute), false);
        foreach (PerformanceMonitorAttribute perfMon in perfMonitors)
        {
            Console.WriteLine($"  Performance Monitor: Category={perfMon.Category}, " +
                            $"LogExecution={perfMon.LogExecution}, MeasureTime={perfMon.MeasureTime}");
        }
    }
}
مثال Attribute-based Method Interceptor:
// پیاده‌سازی ساده Method Interceptor با Attributes
public class MethodInterceptor
{
    public static T ExecuteWithAttributes<T>(Func<T> method, MethodInfo methodInfo)
    {
        var perfAttr = methodInfo.GetCustomAttribute<PerformanceMonitorAttribute>();
        
        if (perfAttr == null)
        {
            return method();
        }

        var stopwatch = System.Diagnostics.Stopwatch.StartNew();
        
        if (perfAttr.LogExecution)
        {
            Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Starting execution of {methodInfo.Name} (Category: {perfAttr.Category})");
        }

        try
        {
            T result = method();
            
            stopwatch.Stop();
            
            if (perfAttr.MeasureTime)
            {
                Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {methodInfo.Name} completed in {stopwatch.ElapsedMilliseconds}ms");
            }
            
            if (perfAttr.LogExecution)
            {
                Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {methodInfo.Name} executed successfully");
            }

            return result;
        }
        catch (Exception ex)
        {
            stopwatch.Stop();
            Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {methodInfo.Name} failed after {stopwatch.ElapsedMilliseconds}ms: {ex.Message}");
            throw;
        }
    }

    public static void ExecuteWithAttributes(Action method, MethodInfo methodInfo)
    {
        ExecuteWithAttributes(() => { method(); return 0; }, methodInfo);
    }
}

public static void DemonstrateMethodInterceptor()
{
    Console.WriteLine("=== Method Interceptor with Attributes ===");

    var calculator = new Calculator();
    var calculatorType = typeof(Calculator);

    // اجرای متد Add با monitoring
    var addMethod = calculatorType.GetMethod("Add");
    int addResult = MethodInterceptor.ExecuteWithAttributes(
        () => calculator.Add(10, 20), 
        addMethod
    );
    Console.WriteLine($"Add Result: {addResult}\n");

    // اجرای متد Multiply با monitoring
    var multiplyMethod = calculatorType.GetMethod("Multiply");
    int multiplyResult = MethodInterceptor.ExecuteWithAttributes(
        () => calculator.Multiply(5, 6), 
        multiplyMethod
    );
    Console.WriteLine($"Multiply Result: {multiplyResult}\n");

    // اجرای متد CalculateSquareRoot با monitoring
    var sqrtMethod = calculatorType.GetMethod("CalculateSquareRoot");
    double sqrtResult = MethodInterceptor.ExecuteWithAttributes(
        () => calculator.CalculateSquareRoot(16), 
        sqrtMethod
    );
    Console.WriteLine($"Square Root Result: {sqrtResult}\n");

    // تست خطا
    try
    {
        MethodInterceptor.ExecuteWithAttributes(
            () => calculator.CalculateSquareRoot(-4), 
            sqrtMethod
        );
    }
    catch (ArgumentException ex)
    {
        Console.WriteLine($"Expected error caught: {ex.Message}");
    }
}
بهترین شیوه‌های استفاده از Attributes:

۵۷. Generic Constraints در C# چیست؟

پاسخ:

Generic Constraints (محدودیت‌های عمومی) قوانینی هستند که بر روی type parameters در Generic classes، methods و interfaces اعمال می‌شوند. این محدودیت‌ها مشخص می‌کنند که چه نوع انواع داده‌ای می‌توانند به عنوان type argument استفاده شوند. استفاده از constraints امکان دسترسی به اعضای خاص types را فراهم می‌کند و type safety را افزایش می‌دهد.

انواع Generic Constraints:
مثال‌های مختلف Constraints:
using System;
using System.Collections.Generic;

// Interface برای مثال‌ها
public interface IComparable<T>
{
    int CompareTo(T other);
}

public interface IDisplayable
{
    void Display();
    string GetDisplayText();
}

// Base class برای مثال‌ها
public abstract class Shape : IDisplayable
{
    public string Name { get; set; }
    public abstract double GetArea();
    
    public virtual void Display()
    {
        Console.WriteLine($"Shape: {Name}, Area: {GetArea():F2}");
    }
    
    public virtual string GetDisplayText()
    {
        return $"{Name} (Area: {GetArea():F2})";
    }
}

public class Circle : Shape
{
    public double Radius { get; set; }
    
    public Circle() { Name = "Circle"; }
    
    public Circle(double radius) : this()
    {
        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() { Name = "Rectangle"; }
    
    public Rectangle(double width, double height) : this()
    {
        Width = width;
        Height = height;
    }
    
    public override double GetArea()
    {
        return Width * Height;
    }
}

// مثال class constraint
public class ShapeManager<T> where T : Shape, new()
{
    private List<T> shapes = new List<T>();
    
    public void AddShape(T shape)
    {
        shapes.Add(shape);
        Console.WriteLine($"Added {shape.GetDisplayText()}");
    }
    
    public T CreateDefaultShape()
    {
        return new T(); // امکان استفاده از new() به دلیل constraint
    }
    
    public void DisplayAllShapes()
    {
        Console.WriteLine($"Total {typeof(T).Name}s: {shapes.Count}");
        foreach (var shape in shapes)
        {
            shape.Display(); // امکان فراخوانی Display به دلیل Shape constraint
        }
    }
    
    public double GetTotalArea()
    {
        double total = 0;
        foreach (var shape in shapes)
        {
            total += shape.GetArea(); // امکان فراخوانی GetArea به دلیل Shape constraint
        }
        return total;
    }
}

// مثال interface constraint
public class DisplayManager<T> where T : IDisplayable
{
    private List<T> items = new List<T>();
    
    public void AddItem(T item)
    {
        items.Add(item);
    }
    
    public void DisplayAll()
    {
        Console.WriteLine($"Displaying {items.Count} items:");
        foreach (var item in items)
        {
            item.Display(); // امکان فراخوانی Display به دلیل IDisplayable constraint
        }
    }
    
    public List<string> GetAllDisplayTexts()
    {
        var texts = new List<string>();
        foreach (var item in items)
        {
            texts.Add(item.GetDisplayText()); // امکان فراخوانی GetDisplayText
        }
        return texts;
    }
}

// مثال struct constraint
public class ValueTypeProcessor<T> where T : struct
{
    public void ProcessValue(T value)
    {
        Console.WriteLine($"Processing value type: {value} (Type: {typeof(T).Name})");
        Console.WriteLine($"Default value: {default(T)}");
        Console.WriteLine($"Is value type: {typeof(T).IsValueType}");
    }
    
    public T[] CreateArray(int size, T defaultValue)
    {
        var array = new T[size];
        for (int i = 0; i < size; i++)
        {
            array[i] = defaultValue;
        }
        return array;
    }
}

// مثال reference type constraint
public class ReferenceTypeManager<T> where T : class
{
    private T _cachedItem;
    
    public void SetItem(T item)
    {
        _cachedItem = item;
        Console.WriteLine($"Set item: {(item != null ? item.ToString() : "null")}");
    }
    
    public T GetItem()
    {
        return _cachedItem;
    }
    
    public bool HasItem()
    {
        return _cachedItem != null; // امکان مقایسه با null به دلیل class constraint
    }
    
    public void ClearItem()
    {
        _cachedItem = null; // امکان انتساب null به دلیل class constraint
    }
}

public static void DemonstrateGenericConstraints()
{
    Console.WriteLine("=== Generic Constraints Demo ===");
    
    // تست Shape constraint
    Console.WriteLine("\n--- Shape Manager Demo ---");
    var circleManager = new ShapeManager<Circle>();
    circleManager.AddShape(new Circle(5.0));
    circleManager.AddShape(new Circle(3.0));
    
    var defaultCircle = circleManager.CreateDefaultShape();
    Console.WriteLine($"Created default circle: {defaultCircle.GetDisplayText()}");
    
    circleManager.DisplayAllShapes();
    Console.WriteLine($"Total area: {circleManager.GetTotalArea():F2}");
    
    // تست Interface constraint
    Console.WriteLine("\n--- Display Manager Demo ---");
    var displayManager = new DisplayManager<Shape>();
    displayManager.AddItem(new Circle(4.0));
    displayManager.AddItem(new Rectangle(3.0, 4.0));
    displayManager.DisplayAll();
    
    var displayTexts = displayManager.GetAllDisplayTexts();
    Console.WriteLine("Display texts:");
    displayTexts.ForEach(text => Console.WriteLine($"- {text}"));
    
    // تست struct constraint
    Console.WriteLine("\n--- Value Type Processor Demo ---");
    var intProcessor = new ValueTypeProcessor<int>();
    intProcessor.ProcessValue(42);
    
    var intArray = intProcessor.CreateArray(5, 10);
    Console.WriteLine($"Created array: [{string.Join(", ", intArray)}]");
    
    var doubleProcessor = new ValueTypeProcessor<double>();
    doubleProcessor.ProcessValue(3.14);
    
    // تست class constraint
    Console.WriteLine("\n--- Reference Type Manager Demo ---");
    var stringManager = new ReferenceTypeManager<string>();
    stringManager.SetItem("Hello World");
    Console.WriteLine($"Has item: {stringManager.HasItem()}");
    Console.WriteLine($"Get item: {stringManager.GetItem()}");
    
    stringManager.ClearItem();
    Console.WriteLine($"After clear - Has item: {stringManager.HasItem()}");
}
مثال Multiple Constraints:
// کلاس با multiple constraints
public class AdvancedProcessor<T> where T : class, IDisplayable, new()
{
    private List<T> items = new List<T>();
    
    public T CreateAndAddItem()
    {
        var newItem = new T(); // امکان استفاده از new() constructor
        items.Add(newItem);
        
        if (newItem != null) // امکان null check به دلیل class constraint
        {
            newItem.Display(); // امکان فراخوانی Display به دلیل IDisplayable constraint
        }
        
        return newItem;
    }
    
    public void ProcessItems()
    {
        Console.WriteLine($"Processing {items.Count} items:");
        foreach (var item in items)
        {
            if (item != null) // class constraint
            {
                item.Display(); // IDisplayable constraint
            }
        }
    }
}

// کلاس برای تست multiple constraints
public class Product : IDisplayable
{
    public string Name { get; set; } = "Default Product";
    public decimal Price { get; set; } = 0;
    
    public Product() { }
    
    public Product(string name, decimal price)
    {
        Name = name;
        Price = price;
    }
    
    public void Display()
    {
        Console.WriteLine($"Product: {Name}, Price: ${Price:F2}");
    }
    
    public string GetDisplayText()
    {
        return $"{Name} (${Price:F2})";
    }
}

// مثال Generic Method با constraints
public static class GenericMethods
{
    // متد با type constraint
    public static void CompareAndDisplay<T>(T item1, T item2) where T : IComparable<T>, IDisplayable
    {
        Console.WriteLine("Comparing items:");
        item1.Display();
        item2.Display();
        
        int comparison = item1.CompareTo(item2);
        string result = comparison == 0 ? "equal to" : 
                       comparison < 0 ? "less than" : "greater than";
        
        Console.WriteLine($"Result: First item is {result} second item");
    }
    
    // متد با struct constraint
    public static T GetDefault<T>() where T : struct
    {
        return default(T);
    }
    
    // متد با class constraint
    public static bool IsNull<T>(T item) where T : class
    {
        return item == null;
    }
    
    // متد با new() constraint
    public static List<T> CreateList<T>(int count) where T : new()
    {
        var list = new List<T>();
        for (int i = 0; i < count; i++)
        {
            list.Add(new T());
        }
        return list;
    }
}

public static void DemonstrateMultipleConstraints()
{
    Console.WriteLine("\n=== Multiple Constraints Demo ===");
    
    // تست AdvancedProcessor
    var processor = new AdvancedProcessor<Product>();
    var product1 = processor.CreateAndAddItem();
    product1.Name = "لپ‌تاپ";
    product1.Price = 1500;
    
    var product2 = processor.CreateAndAddItem();
    product2.Name = "موس";
    product2.Price = 25;
    
    processor.ProcessItems();
    
    // تست Generic Methods
    Console.WriteLine("\n--- Generic Methods Demo ---");
    
    // تست struct constraint
    int defaultInt = GenericMethods.GetDefault<int>();
    double defaultDouble = GenericMethods.GetDefault<double>();
    Console.WriteLine($"Default int: {defaultInt}, Default double: {defaultDouble}");
    
    // تست class constraint
    string testString = "Hello";
    string nullString = null;
    Console.WriteLine($"Is 'Hello' null: {GenericMethods.IsNull(testString)}");
    Console.WriteLine($"Is null string null: {GenericMethods.IsNull(nullString)}");
    
    // تست new() constraint
    var productList = GenericMethods.CreateList<Product>(3);
    Console.WriteLine($"Created {productList.Count} products:");
    productList.ForEach(p => p.Display());
}
مزایای استفاده از Generic Constraints:

۵۸. Nullable Value Types در C# چیست؟

پاسخ:

Nullable Value Types امکان انتساب مقدار null به value types را فراهم می‌کنند. در C#، value types به طور پیش‌فرض نمی‌توانند null باشند، اما با استفاده از Nullable<T> یا سینتکس کوتاه T? می‌توان این محدودیت را برطرف کرد. این ویژگی برای کار با پایگاه‌های داده، APIها و سناریوهایی که مقدار ممکن است موجود نباشد بسیار مفید است.

ویژگی‌های Nullable Value Types:
مثال‌های پایه:
using System;

public static void DemonstrateNullableBasics()
{
    Console.WriteLine("=== Nullable Value Types Basics ===");
    
    // تعریف Nullable types
    int? nullableInt = null;
    double? nullableDouble = 3.14;
    bool? nullableBool = true;
    DateTime? nullableDateTime = null;
    
    Console.WriteLine($"nullableInt: {nullableInt}");
    Console.WriteLine($"nullableDouble: {nullableDouble}");
    Console.WriteLine($"nullableBool: {nullableBool}");
    Console.WriteLine($"nullableDateTime: {nullableDateTime}");
    
    // بررسی HasValue
    Console.WriteLine($"\nnullableInt HasValue: {nullableInt.HasValue}");
    Console.WriteLine($"nullableDouble HasValue: {nullableDouble.HasValue}");
    
    // دسترسی به Value
    if (nullableDouble.HasValue)
    {
        Console.WriteLine($"nullableDouble Value: {nullableDouble.Value}");
    }
    
    // استفاده از GetValueOrDefault
    Console.WriteLine($"nullableInt GetValueOrDefault(): {nullableInt.GetValueOrDefault()}");
    Console.WriteLine($"nullableInt GetValueOrDefault(100): {nullableInt.GetValueOrDefault(100)}");
    
    // انتساب مقادیر
    nullableInt = 42;
    nullableDateTime = DateTime.Now;
    
    Console.WriteLine($"\nAfter assignment:");
    Console.WriteLine($"nullableInt: {nullableInt}");
    Console.WriteLine($"nullableDateTime: {nullableDateTime}");
    
    // تبدیل به null
    nullableInt = null;
    Console.WriteLine($"nullableInt after setting to null: {nullableInt}");
}

// کلاس برای نمایش کاربرد عملی
public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime? HireDate { get; set; } // ممکن است هنوز استخدام نشده باشد
    public decimal? Salary { get; set; } // ممکن است حقوق مشخص نشده باشد
    public int? Age { get; set; } // ممکن است سن مشخص نباشد
    public bool? IsActive { get; set; } // ممکن است وضعیت مشخص نباشد
    
    public Employee(int id, string name)
    {
        Id = id;
        Name = name;
    }
    
    public void DisplayInfo()
    {
        Console.WriteLine($"Employee: {Name} (ID: {Id})");
        Console.WriteLine($"  Hire Date: {(HireDate.HasValue ? HireDate.Value.ToString("yyyy-MM-dd") : "Not specified")}");
        Console.WriteLine($"  Salary: {(Salary.HasValue ? $"${Salary.Value:N0}" : "Not specified")}");
        Console.WriteLine($"  Age: {(Age.HasValue ? Age.Value.ToString() : "Not specified")}");
        Console.WriteLine($"  Status: {(IsActive.HasValue ? (IsActive.Value ? "Active" : "Inactive") : "Unknown")}");
    }
    
    public int GetYearsOfService()
    {
        if (!HireDate.HasValue)
        {
            throw new InvalidOperationException("Hire date is not specified");
        }
        
        return DateTime.Now.Year - HireDate.Value.Year;
    }
    
    public decimal GetAnnualSalary()
    {
        return Salary ?? 0; // استفاده از null coalescing operator
    }
    
    public string GetAgeGroup()
    {
        if (!Age.HasValue)
            return "Unknown";
            
        if (Age.Value < 30)
            return "Young";
        else if (Age.Value < 50)
            return "Middle-aged";
        else
            return "Senior";
    }
}

public static void DemonstrateNullableInPractice()
{
    Console.WriteLine("\n=== Nullable Types in Practice ===");
    
    // ایجاد کارمندان با اطلاعات ناقص
    var employee1 = new Employee(1, "احمد محمدی")
    {
        HireDate = new DateTime(2020, 3, 15),
        Salary = 75000,
        Age = 28,
        IsActive = true
    };
    
    var employee2 = new Employee(2, "فاطمه احمدی")
    {
        HireDate = new DateTime(2019, 7, 10),
        // Salary و Age مشخص نشده
        IsActive = true
    };
    
    var employee3 = new Employee(3, "علی رضایی")
    {
        // هیچ اطلاعات اضافی مشخص نشده
    };
    
    var employees = new[] { employee1, employee2, employee3 };
    
    foreach (var emp in employees)
    {
        emp.DisplayInfo();
        
        // محاسبه سال‌های خدمت
        try
        {
            int yearsOfService = emp.GetYearsOfService();
            Console.WriteLine($"  Years of Service: {yearsOfService}");
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine($"  Years of Service: {ex.Message}");
        }
        
        Console.WriteLine($"  Annual Salary: ${emp.GetAnnualSalary():N0}");
        Console.WriteLine($"  Age Group: {emp.GetAgeGroup()}");
        Console.WriteLine();
    }
}
مثال Null Coalescing Operators:
public static void DemonstrateNullCoalescingOperators()
{
    Console.WriteLine("=== Null Coalescing Operators ===");
    
    int? nullableValue = null;
    int? anotherValue = 100;
    
    // Null coalescing operator (??)
    int result1 = nullableValue ?? 50;
    int result2 = anotherValue ?? 50;
    
    Console.WriteLine($"nullableValue ?? 50 = {result1}"); // 50
    Console.WriteLine($"anotherValue ?? 50 = {result2}"); // 100
    
    // Chaining null coalescing
    int? value1 = null;
    int? value2 = null;
    int? value3 = 200;
    
    int chainResult = value1 ?? value2 ?? value3 ?? 0;
    Console.WriteLine($"value1 ?? value2 ?? value3 ?? 0 = {chainResult}"); // 200
    
    // Null coalescing assignment (??=) - C# 8.0+
    int? assignmentValue = null;
    assignmentValue ??= 75; // فقط اگر null باشد مقدار انتساب می‌دهد
    Console.WriteLine($"After ??= 75: {assignmentValue}"); // 75
    
    assignmentValue ??= 150; // چون null نیست، تغییر نمی‌کند
    Console.WriteLine($"After ??= 150: {assignmentValue}"); // 75
    
    // کاربرد عملی در متدها
    string ProcessData(string input, int? maxLength = null, bool? trimWhitespace = null)
    {
        // استفاده از null coalescing برای default values
        int actualMaxLength = maxLength ?? 100;
        bool actualTrimWhitespace = trimWhitespace ?? true;
        
        string result = input ?? string.Empty;
        
        if (actualTrimWhitespace)
        {
            result = result.Trim();
        }
        
        if (result.Length > actualMaxLength)
        {
            result = result.Substring(0, actualMaxLength) + "...";
        }
        
        return result;
    }
    
    Console.WriteLine("\n--- ProcessData Method Examples ---");
    Console.WriteLine($"ProcessData(null): '{ProcessData(null)}'");
    Console.WriteLine($"ProcessData('  Hello World  '): '{ProcessData("  Hello World  ")}'");
    Console.WriteLine($"ProcessData('Long text...', 10): '{ProcessData("This is a very long text that should be truncated", 10)}'");
    Console.WriteLine($"ProcessData('  Spaces  ', null, false): '{ProcessData("  Spaces  ", null, false)}'");
}
مثال کاربردی - Database Integration:
// شبیه‌سازی کلاس برای کار با پایگاه داده
public class DatabaseRecord
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? Age { get; set; }
    public decimal? Salary { get; set; }
    public DateTime? LastLogin { get; set; }
    public bool? IsVerified { get; set; }
    
    // متد برای تبدیل null values به مقادیر پیش‌فرض
    public void SetDefaults()
    {
        Age ??= 0;
        Salary ??= 0;
        LastLogin ??= DateTime.MinValue;
        IsVerified ??= false;
    }
    
    // متد برای بررسی اعتبار داده‌ها
    public List<string> ValidateData()
    {
        var errors = new List<string>();
        
        if (string.IsNullOrWhiteSpace(Name))
            errors.Add("Name is required");
            
        if (Age.HasValue && Age.Value < 0)
            errors.Add("Age cannot be negative");
            
        if (Salary.HasValue && Salary.Value < 0)
            errors.Add("Salary cannot be negative");
            
        if (LastLogin.HasValue && LastLogin.Value > DateTime.Now)
            errors.Add("Last login cannot be in the future");
            
        return errors;
    }
    
    // متد برای نمایش اطلاعات
    public override string ToString()
    {
        return $"Record {Id}: {Name ?? "Unknown"}, " +
               $"Age: {Age?.ToString() ?? "N/A"}, " +
               $"Salary: {(Salary.HasValue ? $"${Salary.Value:N0}" : "N/A")}, " +
               $"Last Login: {(LastLogin.HasValue ? LastLogin.Value.ToString("yyyy-MM-dd") : "Never")}, " +
               $"Verified: {(IsVerified.HasValue ? IsVerified.Value.ToString() : "Unknown")}";
    }
}

public static void DemonstrateDatabaseIntegration()
{
    Console.WriteLine("\n=== Database Integration Example ===");
    
    // شبیه‌سازی داده‌های از پایگاه داده (برخی null)
    var records = new[]
    {
        new DatabaseRecord { Id = 1, Name = "احمد محمدی", Age = 30, Salary = 75000, LastLogin = DateTime.Now.AddDays(-1), IsVerified = true },
        new DatabaseRecord { Id = 2, Name = "فاطمه احمدی", Age = null, Salary = 65000, LastLogin = null, IsVerified = true },
        new DatabaseRecord { Id = 3, Name = "علی رضایی", Age = 25, Salary = null, LastLogin = DateTime.Now.AddDays(-7), IsVerified = null },
        new DatabaseRecord { Id = 4, Name = null, Age = null, Salary = null, LastLogin = null, IsVerified = false }
    };
    
    Console.WriteLine("Original Records:");
    foreach (var record in records)
    {
        Console.WriteLine($"- {record}");
        
        var errors = record.ValidateData();
        if (errors.Any())
        {
            Console.WriteLine($"  Validation Errors: {string.Join(", ", errors)}");
        }
    }
    
    Console.WriteLine("\nAfter Setting Defaults:");
    foreach (var record in records)
    {
        record.SetDefaults();
        Console.WriteLine($"- {record}");
    }
    
    // آمار کلی
    Console.WriteLine("\n--- Statistics ---");
    var validRecords = records.Where(r => !string.IsNullOrWhiteSpace(r.Name)).ToArray();
    
    double averageAge = validRecords
        .Where(r => r.Age.HasValue && r.Age.Value > 0)
        .Average(r => r.Age.Value);
    
    decimal averageSalary = validRecords
        .Where(r => r.Salary.HasValue && r.Salary.Value > 0)
        .Average(r => r.Salary.Value);
    
    int verifiedCount = validRecords.Count(r => r.IsVerified == true);
    int recentLoginCount = validRecords.Count(r => r.LastLogin.HasValue && r.LastLogin.Value > DateTime.Now.AddDays(-30));
    
    Console.WriteLine($"Valid Records: {validRecords.Length}");
    Console.WriteLine($"Average Age: {averageAge:F1}");
    Console.WriteLine($"Average Salary: ${averageSalary:N0}");
    Console.WriteLine($"Verified Users: {verifiedCount}");
    Console.WriteLine($"Recent Logins (30 days): {recentLoginCount}");
}
بهترین شیوه‌های استفاده از Nullable Types:

۵۹. Pattern Matching در C# چیست؟

پاسخ:

Pattern Matching (تطبیق الگو) قابلیتی در C# است که به شما امکان می‌دهد تا ساختار داده‌ها را بررسی کرده و بر اساس آن ساختار، تصمیمات شرطی بگیرید. این قابلیت کد را خواناتر، فشرده‌تر و ایمن‌تر می‌کند، به خصوص هنگام کار با انواع داده‌های مختلف یا سلسله مراتب ارث‌بری. Pattern Matching از C# 7.0 معرفی شده و در نسخه‌های بعدی به طور قابل توجهی بهبود یافته است.

انواع Pattern Matching:
مثال Type Pattern و is Expression:
using System;
using System.Collections.Generic;

// کلاس‌های نمونه برای تست Pattern Matching
public abstract class Shape
{
    public abstract double 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;
    }
}

public class Triangle : Shape
{
    public double Base { get; set; }
    public double Height { get; set; }
    
    public Triangle(double baseLength, double height)
    {
        Base = baseLength;
        Height = height;
    }
    
    public override double GetArea()
    {
        return 0.5 * Base * Height;
    }
}

public static void DemonstrateTypePattern()
{
    Console.WriteLine("=== Type Pattern Examples ===");
    
    var shapes = new Shape[]
    {
        new Circle(5),
        new Rectangle(4, 6),
        new Triangle(3, 8),
        new Circle(2.5)
    };
    
    foreach (var shape in shapes)
    {
        // Type pattern با is expression
        if (shape is Circle circle)
        {
            Console.WriteLine($"Circle with radius {circle.Radius}, Area: {circle.GetArea():F2}");
            
            if (circle.Radius > 3)
            {
                Console.WriteLine("  This is a large circle!");
            }
        }
        else if (shape is Rectangle rectangle)
        {
            Console.WriteLine($"Rectangle {rectangle.Width}×{rectangle.Height}, Area: {rectangle.GetArea():F2}");
            
            if (rectangle.Width == rectangle.Height)
            {
                Console.WriteLine("  This is actually a square!");
            }
        }
        else if (shape is Triangle triangle)
        {
            Console.WriteLine($"Triangle with base {triangle.Base} and height {triangle.Height}, Area: {triangle.GetArea():F2}");
        }
    }
}

// متد با استفاده از switch expression (C# 8.0+)
public static string GetShapeDescription(Shape shape) => shape switch
{
    Circle { Radius: var r } when r > 5 => $"Large circle (radius: {r})",
    Circle { Radius: var r } => $"Circle (radius: {r})",
    Rectangle { Width: var w, Height: var h } when w == h => $"Square ({w}×{h})",
    Rectangle { Width: var w, Height: var h } => $"Rectangle ({w}×{h})",
    Triangle { Base: var b, Height: var h } => $"Triangle (base: {b}, height: {h})",
    _ => "Unknown shape"
};

public static void DemonstrateSwitchExpression()
{
    Console.WriteLine("\n=== Switch Expression Examples ===");
    
    var shapes = new Shape[]
    {
        new Circle(7),
        new Rectangle(5, 5),
        new Triangle(4, 6),
        new Rectangle(3, 8)
    };
    
    foreach (var shape in shapes)
    {
        string description = GetShapeDescription(shape);
        Console.WriteLine($"Shape: {description}, Area: {shape.GetArea():F2}");
    }
}
مثال Property Pattern:
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string City { get; set; }
    public bool IsStudent { get; set; }
    public decimal? Salary { get; set; }
    
    public Person(string name, int age, string city, bool isStudent = false, decimal? salary = null)
    {
        Name = name;
        Age = age;
        City = city;
        IsStudent = isStudent;
        Salary = salary;
    }
}

public static void DemonstratePropertyPattern()
{
    Console.WriteLine("=== Property Pattern Examples ===");
    
    var people = new[]
    {
        new Person("احمد محمدی", 25, "تهران", true),
        new Person("فاطمه احمدی", 30, "اصفهان", false, 75000),
        new Person("علی رضایی", 22, "تهران", true),
        new Person("زهرا محمدی", 35, "شیراز", false, 85000),
        new Person("حسن احمدی", 28, "تهران", false, 65000)
    };
    
    foreach (var person in people)
    {
        // Property pattern با switch expression
        string category = person switch
        {
            { Age: < 25, IsStudent: true } => "Young Student",
            { Age: >= 25, Age: < 30, IsStudent: true } => "Adult Student",
            { Age: < 30, IsStudent: false, Salary: null } => "Young Job Seeker",
            { Age: < 30, IsStudent: false, Salary: not null } => "Young Professional",
            { Age: >= 30, Salary: > 80000 } => "Senior Professional",
            { Age: >= 30, Salary: <= 80000 and not null } => "Mid-level Professional",
            { City: "تهران", Age: > 25 } => "Tehran Resident",
            _ => "General Category"
        };
        
        Console.WriteLine($"{person.Name} ({person.Age}, {person.City}): {category}");
        
        // Property pattern با if statement
        if (person is { City: "تهران", Age: > 20, Age: < 30 })
        {
            Console.WriteLine("  → Young Tehran resident");
        }
        
        if (person is { IsStudent: false, Salary: > 70000 })
        {
            Console.WriteLine("  → High earner");
        }
    }
}

// مثال پیچیده‌تر با nested properties
public class Employee
{
    public string Name { get; set; }
    public Department Department { get; set; }
    public Address Address { get; set; }
    public decimal Salary { get; set; }
    
    public Employee(string name, Department dept, Address addr, decimal salary)
    {
        Name = name;
        Department = dept;
        Address = addr;
        Salary = salary;
    }
}

public class Department
{
    public string Name { get; set; }
    public string Manager { get; set; }
    
    public Department(string name, string manager)
    {
        Name = name;
        Manager = manager;
    }
}

public class Address
{
    public string City { get; set; }
    public string Country { get; set; }
    
    public Address(string city, string country)
    {
        City = city;
        Country = country;
    }
}

public static void DemonstrateNestedPropertyPattern()
{
    Console.WriteLine("\n=== Nested Property Pattern Examples ===");
    
    var employees = new[]
    {
        new Employee("احمد محمدی", new Department("IT", "مدیر فنی"), new Address("تهران", "ایران"), 80000),
        new Employee("فاطمه احمدی", new Department("HR", "مدیر منابع انسانی"), new Address("اصفهان", "ایران"), 70000),
        new Employee("John Smith", new Department("IT", "Tech Manager"), new Address("New York", "USA"), 95000),
        new Employee("علی رضایی", new Department("Finance", "مدیر مالی"), new Address("شیراز", "ایران"), 75000)
    };
    
    foreach (var emp in employees)
    {
        // Nested property pattern
        string bonus = emp switch
        {
            { Department: { Name: "IT" }, Address: { Country: "ایران" }, Salary: > 75000 } => "High IT Bonus",
            { Department: { Name: "IT" }, Address: { Country: "USA" } } => "International IT Bonus",
            { Department: { Name: "HR" }, Address: { City: "اصفهان" } } => "Regional HR Bonus",
            { Salary: > 80000 } => "High Salary Bonus",
            { Address: { Country: "ایران" } } => "Local Bonus",
            _ => "Standard Bonus"
        };
        
        Console.WriteLine($"{emp.Name} ({emp.Department.Name}, {emp.Address.City}): {bonus}");
    }
}
مثال Positional Pattern و Tuples:
public static void DemonstratePositionalPattern()
{
    Console.WriteLine("=== Positional Pattern Examples ===");
    
    // Tuple patterns
    var coordinates = new[]
    {
        (0, 0),
        (1, 0),
        (0, 1),
        (1, 1),
        (2, 3),
        (-1, -1)
    };
    
    foreach (var (x, y) in coordinates)
    {
        string quadrant = (x, y) switch
        {
            (0, 0) => "Origin",
            (var a, 0) when a > 0 => "Positive X-axis",
            (var a, 0) when a < 0 => "Negative X-axis",
            (0, var b) when b > 0 => "Positive Y-axis",
            (0, var b) when b < 0 => "Negative Y-axis",
            (> 0, > 0) => "First Quadrant",
            (< 0, > 0) => "Second Quadrant",
            (< 0, < 0) => "Third Quadrant",
            (> 0, < 0) => "Fourth Quadrant"
        };
        
        Console.WriteLine($"Point ({x}, {y}): {quadrant}");
    }
    
    // Record types با positional patterns
    var people = new[]
    {
        new PersonRecord("احمد", "محمدی", 25),
        new PersonRecord("فاطمه", "احمدی", 30),
        new PersonRecord("علی", "رضایی", 22)
    };
    
    foreach (var person in people)
    {
        string greeting = person switch
        {
            ("احمد", _, var age) when age < 30 => $"سلام احمد جان! {age} ساله هستی.",
            (var first, "احمدی", _) => $"سلام {first} احمدی!",
            (_, _, > 25) => $"سلام! شما بالای 25 سال سن دارید.",
            _ => "سلام!"
        };
        
        Console.WriteLine($"{person}: {greeting}");
    }
}

// Record type برای positional pattern
public record PersonRecord(string FirstName, string LastName, int Age);
مثال List Pattern (C# 11):
public static void DemonstrateListPattern()
{
    Console.WriteLine("=== List Pattern Examples (C# 11) ===");
    
    var arrays = new int[][]
    {
        new[] { 1 },
        new[] { 1, 2 },
        new[] { 1, 2, 3 },
        new[] { 1, 2, 3, 4 },
        new[] { 5, 10, 15 },
        Array.Empty<int>()
    };
    
    foreach (var array in arrays)
    {
        string description = array switch
        {
            [] => "Empty array",
            [var single] => $"Single element: {single}",
            [var first, var second] => $"Two elements: {first}, {second}",
            [1, 2, 3] => "Exact match: 1, 2, 3",
            [var first, .., var last] => $"Multiple elements: first={first}, last={last}",
            _ => "Other pattern"
        };
        
        Console.WriteLine($"[{string.Join(", ", array)}]: {description}");
    }
    
    // List pattern با شرایط
    var sequences = new[]
    {
        new[] { 1, 2, 3, 4, 5 },
        new[] { 10, 20, 30 },
        new[] { 1, 1, 1, 1 },
        new[] { 5 }
    };
    
    Console.WriteLine("\nList Pattern with Conditions:");
    foreach (var seq in sequences)
    {
        string analysis = seq switch
        {
            [var first, .. var rest] when rest.All(x => x == first) => "All elements are the same",
            [var first, .. var middle, var last] when first == last => "First and last are equal",
            [.. var elements] when elements.Length > 3 => "More than 3 elements",
            [var only] when only > 5 => "Single large element",
            _ => "Other sequence"
        };
        
        Console.WriteLine($"[{string.Join(", ", seq)}]: {analysis}");
    }
}
مزایای Pattern Matching:

۶۰. Records در C# چیست؟

پاسخ:

Records یک نوع reference type جدید در C# 9 هستند که برای تعریف کلاس‌هایی با معنای برابری مبتنی بر مقدار (Value-based Equality) طراحی شده‌اند. هدف اصلی Records، ساده‌سازی ایجاد انواع داده‌های تغییرناپذیر (Immutable Data Types) است که عمدتاً برای نگهداری داده‌ها (Data Holders) استفاده می‌شوند. Records بسیاری از کدهای boilerplate مانند Equals، GetHashCode و ToString را به صورت خودکار تولید می‌کنند.

ویژگی‌های کلیدی Records:
مثال‌های پایه Records:
using System;

// Record با positional syntax (compact form)
public record Person(string FirstName, string LastName, int Age);

// Record با property syntax (traditional form)
public record Employee
{
    public string Name { get; init; }
    public string Department { get; init; }
    public decimal Salary { get; init; }
    public DateTime HireDate { get; init; }
    
    public Employee(string name, string department, decimal salary, DateTime hireDate)
    {
        Name = name;
        Department = department;
        Salary = salary;
        HireDate = hireDate;
    }
}

// Record با mixed approach
public record Product(string Name, decimal Price)
{
    public string Category { get; init; } = "General";
    public bool IsAvailable { get; init; } = true;
    public DateTime CreatedDate { get; init; } = DateTime.Now;
    
    // Custom method
    public decimal GetDiscountedPrice(decimal discountPercent)
    {
        return Price * (1 - discountPercent / 100);
    }
    
    // Override ToString for custom formatting
    public override string ToString()
    {
        return $"{Name} - ${Price:F2} ({Category}) - Available: {IsAvailable}";
    }
}

public static void DemonstrateBasicRecords()
{
    Console.WriteLine("=== Basic Records Examples ===");
    
    // ایجاد Person records
    var person1 = new Person("احمد", "محمدی", 30);
    var person2 = new Person("فاطمه", "احمدی", 28);
    var person3 = new Person("احمد", "محمدی", 30); // مشابه person1
    
    Console.WriteLine($"Person1: {person1}");
    Console.WriteLine($"Person2: {person2}");
    Console.WriteLine($"Person3: {person3}");
    
    // Value-based equality
    Console.WriteLine($"\nperson1 == person2: {person1 == person2}"); // False
    Console.WriteLine($"person1 == person3: {person1 == person3}"); // True
    Console.WriteLine($"person1.Equals(person3): {person1.Equals(person3)}"); // True
    
    // Deconstruction
    var (firstName, lastName, age) = person1;
    Console.WriteLine($"Deconstructed: {firstName} {lastName}, {age} years old");
    
    // Employee record
    var employee = new Employee("علی رضایی", "IT", 75000, new DateTime(2020, 3, 15));
    Console.WriteLine($"\nEmployee: {employee}");
    
    // Product record
    var product = new Product("لپ‌تاپ", 1500)
    {
        Category = "Electronics",
        IsAvailable = true
    };
    
    Console.WriteLine($"Product: {product}");
    Console.WriteLine($"Discounted Price (10%): ${product.GetDiscountedPrice(10):F2}");
}
مثال with Expression:
public static void DemonstrateWithExpression()
{
    Console.WriteLine("=== with Expression Examples ===");
    
    var originalPerson = new Person("احمد", "محمدی", 30);
    Console.WriteLine($"Original: {originalPerson}");
    
    // ایجاد کپی جدید با تغییر سن
    var olderPerson = originalPerson with { Age = 31 };
    Console.WriteLine($"Older: {olderPerson}");
    
    // ایجاد کپی جدید با تغییر نام خانوادگی
    var marriedPerson = originalPerson with { LastName = "رضایی" };
    Console.WriteLine($"Married: {marriedPerson}");
    
    // تغییر چندین property
    var differentPerson = originalPerson with { FirstName = "علی", Age = 25 };
    Console.WriteLine($"Different: {differentPerson}");
    
    // with expression با Employee
    var originalEmployee = new Employee("فاطمه احمدی", "HR", 65000, DateTime.Now.AddYears(-2));
    Console.WriteLine($"\nOriginal Employee: {originalEmployee}");
    
    // ارتقا حقوق
    var promotedEmployee = originalEmployee with { Salary = 80000, Department = "Senior HR" };
    Console.WriteLine($"Promoted Employee: {promotedEmployee}");
    
    // with expression با Product
    var originalProduct = new Product("کیبورد", 50) { Category = "Accessories" };
    Console.WriteLine($"\nOriginal Product: {originalProduct}");
    
    // تغییر قیمت و دسته‌بندی
    var updatedProduct = originalProduct with { Price = 45, Category = "Gaming Accessories" };
    Console.WriteLine($"Updated Product: {updatedProduct}");
    
    // Chaining with expressions
    var finalProduct = originalProduct with { Price = 40 } with { IsAvailable = false };
    Console.WriteLine($"Final Product: {finalProduct}");
}
مثال Record Inheritance:
// Base record
public record Vehicle(string Brand, string Model, int Year)
{
    public virtual string GetInfo() => $"{Year} {Brand} {Model}";
}

// Derived records
public record Car(string Brand, string Model, int Year, int Doors, string FuelType) 
    : Vehicle(Brand, Model, Year)
{
    public override string GetInfo() => $"{base.GetInfo()} - {Doors} doors, {FuelType}";
}

public record Motorcycle(string Brand, string Model, int Year, int EngineCC) 
    : Vehicle(Brand, Model, Year)
{
    public override string GetInfo() => $"{base.GetInfo()} - {EngineCC}cc";
}

public record ElectricCar(string Brand, string Model, int Year, int Doors, int BatteryCapacity) 
    : Car(Brand, Model, Year, Doors, "Electric")
{
    public int Range { get; init; } = 300; // km
    
    public override string GetInfo() => $"{base.GetInfo()}, {BatteryCapacity}kWh battery, {Range}km range";
}

public static void DemonstrateRecordInheritance()
{
    Console.WriteLine("=== Record Inheritance Examples ===");
    
    var vehicles = new Vehicle[]
    {
        new Vehicle("Toyota", "Camry", 2022),
        new Car("Honda", "Civic", 2021, 4, "Gasoline"),
        new Motorcycle("Yamaha", "R1", 2023, 1000),
        new ElectricCar("Tesla", "Model 3", 2023, 4, 75) { Range = 500 }
    };
    
    foreach (var vehicle in vehicles)
    {
        Console.WriteLine($"Vehicle: {vehicle.GetInfo()}");
        Console.WriteLine($"  Type: {vehicle.GetType().Name}");
        Console.WriteLine($"  ToString: {vehicle}");
        
        // Pattern matching با records
        string category = vehicle switch
        {
            ElectricCar { Range: > 400 } => "Long-range Electric Vehicle",
            ElectricCar => "Electric Vehicle",
            Car { Doors: 2 } => "Coupe",
            Car { Doors: 4 } => "Sedan",
            Motorcycle { EngineCC: > 600 } => "High-performance Motorcycle",
            Motorcycle => "Motorcycle",
            _ => "General Vehicle"
        };
        
        Console.WriteLine($"  Category: {category}");
        Console.WriteLine();
    }
    
    // Record equality با inheritance
    var car1 = new Car("Honda", "Civic", 2021, 4, "Gasoline");
    var car2 = new Car("Honda", "Civic", 2021, 4, "Gasoline");
    var electricCar = new ElectricCar("Tesla", "Model 3", 2023, 4, 75);
    
    Console.WriteLine("=== Record Equality with Inheritance ===");
    Console.WriteLine($"car1 == car2: {car1 == car2}"); // True
    Console.WriteLine($"car1.Equals(car2): {car1.Equals(car2)}"); // True
    
    // Different types are not equal even with same base properties
    var vehicle1 = new Vehicle("Honda", "Civic", 2021);
    Console.WriteLine($"vehicle1 == car1: {vehicle1 == car1}"); // False
}
مثال کاربردی - Data Transfer Objects:
// DTOs برای API
public record UserDto(int Id, string Username, string Email)
{
    public DateTime CreatedAt { get; init; } = DateTime.UtcNow;
    public bool IsActive { get; init; } = true;
}

public record CreateUserRequest(string Username, string Email, string Password);

public record UpdateUserRequest(string? Username = null, string? Email = null, bool? IsActive = null);

public record UserResponse(int Id, string Username, string Email, DateTime CreatedAt, bool IsActive);

// Event sourcing records
public abstract record DomainEvent(Guid Id, DateTime Timestamp);

public record UserCreated(Guid Id, DateTime Timestamp, string Username, string Email) 
    : DomainEvent(Id, Timestamp);

public record UserUpdated(Guid Id, DateTime Timestamp, string? Username, string? Email, bool? IsActive) 
    : DomainEvent(Id, Timestamp);

public record UserDeleted(Guid Id, DateTime Timestamp, string Reason) 
    : DomainEvent(Id, Timestamp);

// Configuration records
public record DatabaseConfig(string ConnectionString, int TimeoutSeconds = 30, bool EnableLogging = false);

public record ApiConfig(string BaseUrl, string ApiKey, int RetryCount = 3)
{
    public TimeSpan Timeout { get; init; } = TimeSpan.FromSeconds(30);
}

public static void DemonstratePracticalRecords()
{
    Console.WriteLine("=== Practical Records Examples ===");
    
    // DTO usage
    var createRequest = new CreateUserRequest("ahmad.mohammadi", "[email protected]", "password123");
    Console.WriteLine($"Create Request: {createRequest}");
    
    var user = new UserDto(1, createRequest.Username, createRequest.Email);
    Console.WriteLine($"Created User: {user}");
    
    // Update using with expression
    var updateRequest = new UpdateUserRequest(Email: "[email protected]", IsActive: false);
    var updatedUser = user with 
    { 
        Username = updateRequest.Username ?? user.Username,
        Email = updateRequest.Email ?? user.Email,
        IsActive = updateRequest.IsActive ?? user.IsActive
    };
    
    Console.WriteLine($"Updated User: {updatedUser}");
    
    // Event sourcing
    var events = new DomainEvent[]
    {
        new UserCreated(Guid.NewGuid(), DateTime.UtcNow, "ahmad.mohammadi", "[email protected]"),
        new UserUpdated(Guid.NewGuid(), DateTime.UtcNow.AddMinutes(5), null, "[email protected]", null),
        new UserDeleted(Guid.NewGuid(), DateTime.UtcNow.AddMinutes(10), "User requested account deletion")
    };
    
    Console.WriteLine("\nDomain Events:");
    foreach (var evt in events)
    {
        Console.WriteLine($"- {evt.GetType().Name}: {evt}");
    }
    
    // Configuration
    var dbConfig = new DatabaseConfig("Server=localhost;Database=MyApp", EnableLogging: true);
    var apiConfig = new ApiConfig("https://api.example.com", "secret-key") 
    { 
        Timeout = TimeSpan.FromSeconds(60) 
    };
    
    Console.WriteLine($"\nDatabase Config: {dbConfig}");
    Console.WriteLine($"API Config: {apiConfig}");
    
    // Configuration updates
    var prodDbConfig = dbConfig with { ConnectionString = "Server=prod;Database=MyApp", TimeoutSeconds = 60 };
    Console.WriteLine($"Production DB Config: {prodDbConfig}");
}
مقایسه Records با Classes:

۶۱. Extension Methods در C# چیست؟

پاسخ:

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

قوانین تعریف Extension Methods:
مثال‌های پایه:
using System;
using System.Text;
using System.Linq;

// کلاس static برای Extension Methods
public static class StringExtensions
{
    // Extension method برای string
    public static bool IsPalindrome(this string str)
    {
        if (string.IsNullOrEmpty(str))
            return false;
            
        string cleaned = str.ToLower().Replace(" ", "");
        string reversed = new string(cleaned.Reverse().ToArray());
        return cleaned == reversed;
    }
    
    // Extension method با پارامترهای اضافی
    public static string Truncate(this string str, int maxLength, string suffix = "...")
    {
        if (string.IsNullOrEmpty(str) || str.Length <= maxLength)
            return str;
            
        return str.Substring(0, maxLength - suffix.Length) + suffix;
    }
    
    // Extension method برای تبدیل به Title Case
    public static string ToTitleCase(this string str)
    {
        if (string.IsNullOrEmpty(str))
            return str;
            
        var words = str.Split(' ');
        for (int i = 0; i < words.Length; i++)
        {
            if (words[i].Length > 0)
            {
                words[i] = char.ToUpper(words[i][0]) + 
                          (words[i].Length > 1 ? words[i].Substring(1).ToLower() : "");
            }
        }
        return string.Join(" ", words);
    }
    
    // Extension method برای شمارش کلمات
    public static int WordCount(this string str)
    {
        if (string.IsNullOrWhiteSpace(str))
            return 0;
            
        return str.Split(new char[] { ' ', '\t', '\n', '\r' }, 
                        StringSplitOptions.RemoveEmptyEntries).Length;
    }
}

public static class IntExtensions
{
    // Extension method برای بررسی عدد اول
    public static bool IsPrime(this int number)
    {
        if (number < 2) return false;
        if (number == 2) return true;
        if (number % 2 == 0) return false;
        
        for (int i = 3; i * i <= number; i += 2)
        {
            if (number % i == 0)
                return false;
        }
        return true;
    }
    
    // Extension method برای تبدیل به رشته فارسی
    public static string ToPersianString(this int number)
    {
        string[] persianDigits = { "۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹" };
        string result = number.ToString();
        
        for (int i = 0; i < 10; i++)
        {
            result = result.Replace(i.ToString(), persianDigits[i]);
        }
        
        return result;
    }
    
    // Extension method برای محاسبه فاکتوریل
    public static long Factorial(this int number)
    {
        if (number < 0)
            throw new ArgumentException("عدد نمی‌تواند منفی باشد");
            
        if (number == 0 || number == 1)
            return 1;
            
        long result = 1;
        for (int i = 2; i <= number; i++)
        {
            result *= i;
        }
        return result;
    }
}

public static void DemonstrateBasicExtensions()
{
    Console.WriteLine("=== Basic Extension Methods Demo ===");
    
    // استفاده از String Extensions
    string text1 = "A man a plan a canal Panama";
    string text2 = "Hello World";
    string longText = "این یک متن بسیار طولانی است که باید کوتاه شود";
    
    Console.WriteLine($"'{text1}' is palindrome: {text1.IsPalindrome()}");
    Console.WriteLine($"'{text2}' is palindrome: {text2.IsPalindrome()}");
    
    Console.WriteLine($"Truncated: '{longText.Truncate(20)}'");
    Console.WriteLine($"Title case: '{text2.ToLower().ToTitleCase()}'");
    Console.WriteLine($"Word count: {longText.WordCount()}");
    
    // استفاده از Int Extensions
    int number1 = 17;
    int number2 = 1234;
    
    Console.WriteLine($"\n{number1} is prime: {number1.IsPrime()}");
    Console.WriteLine($"{number2} in Persian: {number2.ToPersianString()}");
    Console.WriteLine($"5! = {5.Factorial()}");
}
مثال Collection Extensions:
using System.Collections.Generic;

public static class CollectionExtensions
{
    // Extension method برای بررسی خالی بودن
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> collection)
    {
        return collection == null || !collection.Any();
    }
    
    // Extension method برای اضافه کردن چندین آیتم
    public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
    {
        if (collection == null)
            throw new ArgumentNullException(nameof(collection));
            
        if (items != null)
        {
            foreach (var item in items)
            {
                collection.Add(item);
            }
        }
    }
    
    // Extension method برای تقسیم لیست به chunks
    public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source, int chunkSize)
    {
        if (source == null)
            throw new ArgumentNullException(nameof(source));
            
        if (chunkSize <= 0)
            throw new ArgumentException("Chunk size must be greater than 0");
            
        var list = source.ToList();
        for (int i = 0; i < list.Count; i += chunkSize)
        {
            yield return list.Skip(i).Take(chunkSize);
        }
    }
    
    // Extension method برای shuffle کردن
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
    {
        var random = new Random();
        return source.OrderBy(x => random.Next());
    }
    
    // Extension method برای پیدا کردن آیتم با بیشترین مقدار
    public static T MaxBy<T, TKey>(this IEnumerable<T> source, Func<T, TKey> selector) 
        where TKey : IComparable<TKey>
    {
        if (source == null)
            throw new ArgumentNullException(nameof(source));
            
        using (var enumerator = source.GetEnumerator())
        {
            if (!enumerator.MoveNext())
                throw new InvalidOperationException("Sequence contains no elements");
                
            T maxItem = enumerator.Current;
            TKey maxKey = selector(maxItem);
            
            while (enumerator.MoveNext())
            {
                TKey currentKey = selector(enumerator.Current);
                if (currentKey.CompareTo(maxKey) > 0)
                {
                    maxItem = enumerator.Current;
                    maxKey = currentKey;
                }
            }
            
            return maxItem;
        }
    }
}

public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string Category { get; set; }
    
    public override string ToString()
    {
        return $"{Name} - ${Price:F2} ({Category})";
    }
}

public static void DemonstrateCollectionExtensions()
{
    Console.WriteLine("\n=== Collection Extension Methods Demo ===");
    
    var products = new List<Product>
    {
        new Product { Name = "لپ‌تاپ", Price = 1500, Category = "Electronics" },
        new Product { Name = "موس", Price = 25, Category = "Accessories" },
        new Product { Name = "کیبورد", Price = 75, Category = "Accessories" },
        new Product { Name = "مانیتور", Price = 300, Category = "Electronics" },
        new Product { Name = "هدفون", Price = 150, Category = "Audio" }
    };
    
    // تست IsNullOrEmpty
    List<Product> emptyList = null;
    Console.WriteLine($"Empty list is null or empty: {emptyList.IsNullOrEmpty()}");
    Console.WriteLine($"Products list is null or empty: {products.IsNullOrEmpty()}");
    
    // تست AddRange
    var newProducts = new List<Product>();
    newProducts.AddRange(products.Take(2));
    Console.WriteLine($"Added {newProducts.Count} products using AddRange");
    
    // تست Chunk
    Console.WriteLine("\nProducts in chunks of 2:");
    var chunks = products.Chunk(2);
    int chunkNumber = 1;
    foreach (var chunk in chunks)
    {
        Console.WriteLine($"Chunk {chunkNumber++}:");
        foreach (var product in chunk)
        {
            Console.WriteLine($"  - {product}");
        }
    }
    
    // تست Shuffle
    Console.WriteLine("\nShuffled products:");
    var shuffled = products.Shuffle().Take(3);
    foreach (var product in shuffled)
    {
        Console.WriteLine($"- {product}");
    }
    
    // تست MaxBy
    var mostExpensive = products.MaxBy(p => p.Price);
    Console.WriteLine($"\nMost expensive product: {mostExpensive}");
}
مثال DateTime Extensions:
public static class DateTimeExtensions
{
    // Extension method برای محاسبه سن
    public static int CalculateAge(this DateTime birthDate)
    {
        var today = DateTime.Today;
        var age = today.Year - birthDate.Year;
        
        if (birthDate.Date > today.AddYears(-age))
            age--;
            
        return age;
    }
    
    // Extension method برای تبدیل به تاریخ شمسی (ساده)
    public static string ToPersianDate(this DateTime date)
    {
        var persianCalendar = new System.Globalization.PersianCalendar();
        int year = persianCalendar.GetYear(date);
        int month = persianCalendar.GetMonth(date);
        int day = persianCalendar.GetDayOfMonth(date);
        
        string[] monthNames = {
            "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور",
            "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند"
        };
        
        return $"{day} {monthNames[month - 1]} {year}";
    }
    
    // Extension method برای بررسی آخر هفته
    public static bool IsWeekend(this DateTime date)
    {
        return date.DayOfWeek == DayOfWeek.Friday || date.DayOfWeek == DayOfWeek.Saturday;
    }
    
    // Extension method برای گرفتن اول ماه
    public static DateTime FirstDayOfMonth(this DateTime date)
    {
        return new DateTime(date.Year, date.Month, 1);
    }
    
    // Extension method برای گرفتن آخر ماه
    public static DateTime LastDayOfMonth(this DateTime date)
    {
        return date.FirstDayOfMonth().AddMonths(1).AddDays(-1);
    }
}

public static void DemonstrateDateTimeExtensions()
{
    Console.WriteLine("\n=== DateTime Extension Methods Demo ===");
    
    DateTime birthDate = new DateTime(1990, 5, 15);
    DateTime today = DateTime.Today;
    
    Console.WriteLine($"Birth date: {birthDate:yyyy-MM-dd}");
    Console.WriteLine($"Age: {birthDate.CalculateAge()} years");
    Console.WriteLine($"Persian date: {today.ToPersianDate()}");
    Console.WriteLine($"Is today weekend: {today.IsWeekend()}");
    Console.WriteLine($"First day of month: {today.FirstDayOfMonth():yyyy-MM-dd}");
    Console.WriteLine($"Last day of month: {today.LastDayOfMonth():yyyy-MM-dd}");
}
مزایای Extension Methods:

۶۲. LINQ در C# چیست؟

پاسخ:

LINQ (Language Integrated Query) یک مجموعه از فناوری‌ها در .NET است که قابلیت‌های پرس و جو را مستقیماً به زبان C# اضافه می‌کند. LINQ به شما امکان می‌دهد تا با استفاده از یک سینتکس یکپارچه، داده‌ها را از منابع مختلف پرس و جو کنید (مانند مجموعه‌های درون حافظه، پایگاه‌های داده SQL، اسناد XML). LINQ کد را خواناتر، فشرده‌تر و قابل نگهداری‌تر می‌کند و از خطاهای زمان اجرا جلوگیری می‌کند.

انواع LINQ:
مثال‌های Query Syntax:
using System;
using System.Collections.Generic;
using System.Linq;

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Major { get; set; }
    public double GPA { get; set; }
    public int Age { get; set; }
    public string City { get; set; }
    
    public override string ToString()
    {
        return $"{Name} (ID: {Id}, Major: {Major}, GPA: {GPA:F2}, Age: {Age}, City: {City})";
    }
}

public static void DemonstrateQuerySyntax()
{
    Console.WriteLine("=== LINQ Query Syntax Examples ===");
    
    var students = new List<Student>
    {
        new Student { Id = 1, Name = "احمد محمدی", Major = "Computer Science", GPA = 3.8, Age = 20, City = "تهران" },
        new Student { Id = 2, Name = "فاطمه احمدی", Major = "Mathematics", GPA = 3.9, Age = 22, City = "اصفهان" },
        new Student { Id = 3, Name = "علی رضایی", Major = "Computer Science", GPA = 3.5, Age = 19, City = "تهران" },
        new Student { Id = 4, Name = "زهرا محمدی", Major = "Physics", GPA = 3.7, Age = 21, City = "شیراز" },
        new Student { Id = 5, Name = "حسن احمدی", Major = "Mathematics", GPA = 3.6, Age = 23, City = "تهران" },
        new Student { Id = 6, Name = "مریم رضایی", Major = "Physics", GPA = 3.4, Age = 20, City = "اصفهان" }
    };
    
    // Query syntax - انتخاب دانشجویان با GPA بالا
    var highGpaStudents = from student in students
                         where student.GPA > 3.6
                         orderby student.GPA descending
                         select student;
    
    Console.WriteLine("Students with GPA > 3.6:");
    foreach (var student in highGpaStudents)
    {
        Console.WriteLine($"- {student}");
    }
    
    // Query syntax - انتخاب فیلدهای خاص
    var studentSummary = from student in students
                        where student.City == "تهران"
                        orderby student.Name
                        select new { student.Name, student.Major, student.GPA };
    
    Console.WriteLine("\nTehran students summary:");
    foreach (var summary in studentSummary)
    {
        Console.WriteLine($"- {summary.Name}: {summary.Major} (GPA: {summary.GPA:F2})");
    }
    
    // Query syntax - گروه‌بندی
    var studentsByMajor = from student in students
                         group student by student.Major into majorGroup
                         orderby majorGroup.Key
                         select new 
                         { 
                             Major = majorGroup.Key,
                             Count = majorGroup.Count(),
                             AverageGPA = majorGroup.Average(s => s.GPA),
                             Students = majorGroup.ToList()
                         };
    
    Console.WriteLine("\nStudents grouped by major:");
    foreach (var group in studentsByMajor)
    {
        Console.WriteLine($"- {group.Major}: {group.Count} students, Avg GPA: {group.AverageGPA:F2}");
        foreach (var student in group.Students)
        {
            Console.WriteLine($"  • {student.Name} (GPA: {student.GPA:F2})");
        }
    }
}
مثال‌های Method Syntax:
public static void DemonstrateMethodSyntax()
{
    Console.WriteLine("\n=== LINQ Method Syntax Examples ===");
    
    var students = new List<Student>
    {
        new Student { Id = 1, Name = "احمد محمدی", Major = "Computer Science", GPA = 3.8, Age = 20, City = "تهران" },
        new Student { Id = 2, Name = "فاطمه احمدی", Major = "Mathematics", GPA = 3.9, Age = 22, City = "اصفهان" },
        new Student { Id = 3, Name = "علی رضایی", Major = "Computer Science", GPA = 3.5, Age = 19, City = "تهران" },
        new Student { Id = 4, Name = "زهرا محمدی", Major = "Physics", GPA = 3.7, Age = 21, City = "شیراز" },
        new Student { Id = 5, Name = "حسن احمدی", Major = "Mathematics", GPA = 3.6, Age = 23, City = "تهران" }
    };
    
    // Method syntax - فیلتر و مرتب‌سازی
    var topStudents = students
        .Where(s => s.GPA >= 3.7)
        .OrderByDescending(s => s.GPA)
        .ThenBy(s => s.Age);
    
    Console.WriteLine("Top students (GPA >= 3.7):");
    foreach (var student in topStudents)
    {
        Console.WriteLine($"- {student}");
    }
    
    // Method syntax - تبدیل و انتخاب
    var studentNames = students
        .Where(s => s.City == "تهران")
        .Select(s => s.Name.ToUpper())
        .ToList();
    
    Console.WriteLine($"\nTehran student names: {string.Join(", ", studentNames)}");
    
    // Method syntax - آمار
    var stats = new
    {
        TotalStudents = students.Count(),
        AverageGPA = students.Average(s => s.GPA),
        HighestGPA = students.Max(s => s.GPA),
        LowestGPA = students.Min(s => s.GPA),
        AverageAge = students.Average(s => s.Age),
        CSStudents = students.Count(s => s.Major == "Computer Science")
    };
    
    Console.WriteLine($"\nStatistics:");
    Console.WriteLine($"- Total Students: {stats.TotalStudents}");
    Console.WriteLine($"- Average GPA: {stats.AverageGPA:F2}");
    Console.WriteLine($"- Highest GPA: {stats.HighestGPA:F2}");
    Console.WriteLine($"- Lowest GPA: {stats.LowestGPA:F2}");
    Console.WriteLine($"- Average Age: {stats.AverageAge:F1}");
    Console.WriteLine($"- CS Students: {stats.CSStudents}");
    
    // Method syntax - گروه‌بندی پیشرفته
    var cityMajorGroups = students
        .GroupBy(s => new { s.City, s.Major })
        .Select(g => new
        {
            g.Key.City,
            g.Key.Major,
            Count = g.Count(),
            AverageGPA = g.Average(s => s.GPA),
            Names = string.Join(", ", g.Select(s => s.Name))
        })
        .OrderBy(g => g.City)
        .ThenBy(g => g.Major);
    
    Console.WriteLine("\nStudents grouped by city and major:");
    foreach (var group in cityMajorGroups)
    {
        Console.WriteLine($"- {group.City} - {group.Major}: {group.Count} students");
        Console.WriteLine($"  Average GPA: {group.AverageGPA:F2}");
        Console.WriteLine($"  Students: {group.Names}");
    }
}
مثال‌های پیشرفته LINQ:
public class Course
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Department { get; set; }
    public int Credits { get; set; }
}

public class Enrollment
{
    public int StudentId { get; set; }
    public int CourseId { get; set; }
    public double Grade { get; set; }
    public string Semester { get; set; }
}

public static void DemonstrateAdvancedLinq()
{
    Console.WriteLine("\n=== Advanced LINQ Examples ===");
    
    var students = new List<Student>
    {
        new Student { Id = 1, Name = "احمد محمدی", Major = "Computer Science", GPA = 3.8, Age = 20 },
        new Student { Id = 2, Name = "فاطمه احمدی", Major = "Mathematics", GPA = 3.9, Age = 22 },
        new Student { Id = 3, Name = "علی رضایی", Major = "Computer Science", GPA = 3.5, Age = 19 }
    };
    
    var courses = new List<Course>
    {
        new Course { Id = 101, Name = "Data Structures", Department = "Computer Science", Credits = 3 },
        new Course { Id = 102, Name = "Calculus I", Department = "Mathematics", Credits = 4 },
        new Course { Id = 103, Name = "Physics I", Department = "Physics", Credits = 3 },
        new Course { Id = 104, Name = "Algorithms", Department = "Computer Science", Credits = 3 }
    };
    
    var enrollments = new List<Enrollment>
    {
        new Enrollment { StudentId = 1, CourseId = 101, Grade = 3.7, Semester = "Fall 2023" },
        new Enrollment { StudentId = 1, CourseId = 102, Grade = 3.5, Semester = "Fall 2023" },
        new Enrollment { StudentId = 2, CourseId = 102, Grade = 4.0, Semester = "Fall 2023" },
        new Enrollment { StudentId = 2, CourseId = 103, Grade = 3.8, Semester = "Fall 2023" },
        new Enrollment { StudentId = 3, CourseId = 101, Grade = 3.2, Semester = "Fall 2023" },
        new Enrollment { StudentId = 3, CourseId = 104, Grade = 3.6, Semester = "Fall 2023" }
    };
    
    // Join operations
    var studentCourses = from student in students
                        join enrollment in enrollments on student.Id equals enrollment.StudentId
                        join course in courses on enrollment.CourseId equals course.Id
                        select new
                        {
                            StudentName = student.Name,
                            CourseName = course.Name,
                            Department = course.Department,
                            Credits = course.Credits,
                            Grade = enrollment.Grade,
                            Semester = enrollment.Semester
                        };
    
    Console.WriteLine("Student-Course enrollments:");
    foreach (var sc in studentCourses)
    {
        Console.WriteLine($"- {sc.StudentName}: {sc.CourseName} ({sc.Department}) - Grade: {sc.Grade:F1}, Credits: {sc.Credits}");
    }
    
    // Group Join
    var studentsWithCourses = from student in students
                             join enrollment in enrollments on student.Id equals enrollment.StudentId into studentEnrollments
                             select new
                             {
                                 Student = student,
                                 Courses = from se in studentEnrollments
                                          join course in courses on se.CourseId equals course.Id
                                          select new { course.Name, se.Grade, course.Credits }
                             };
    
    Console.WriteLine("\nStudents with their courses:");
    foreach (var swc in studentsWithCourses)
    {
        Console.WriteLine($"- {swc.Student.Name}:");
        foreach (var course in swc.Courses)
        {
            Console.WriteLine($"  • {course.Name}: Grade {course.Grade:F1} ({course.Credits} credits)");
        }
        
        if (swc.Courses.Any())
        {
            double avgGrade = swc.Courses.Average(c => c.Grade);
            int totalCredits = swc.Courses.Sum(c => c.Credits);
            Console.WriteLine($"  Average Grade: {avgGrade:F2}, Total Credits: {totalCredits}");
        }
    }
    
    // Complex aggregations
    var departmentStats = from course in courses
                         join enrollment in enrollments on course.Id equals enrollment.CourseId
                         group new { course, enrollment } by course.Department into deptGroup
                         select new
                         {
                             Department = deptGroup.Key,
                             CourseCount = deptGroup.Select(x => x.course.Id).Distinct().Count(),
                             EnrollmentCount = deptGroup.Count(),
                             AverageGrade = deptGroup.Average(x => x.enrollment.Grade),
                             TotalCredits = deptGroup.Sum(x => x.course.Credits)
                         };
    
    Console.WriteLine("\nDepartment statistics:");
    foreach (var stat in departmentStats)
    {
        Console.WriteLine($"- {stat.Department}:");
        Console.WriteLine($"  Courses: {stat.CourseCount}, Enrollments: {stat.EnrollmentCount}");
        Console.WriteLine($"  Average Grade: {stat.AverageGrade:F2}, Total Credits: {stat.TotalCredits}");
    }
}
مزایای LINQ:

۶۳. Delegates در C# چیست؟

پاسخ:

Delegates (نمایندگان) در C# یک نوع (Type) هستند که به صورت ایمن برای نوع (Type-safe) به یک یا چند متد اشاره می‌کنند. به عبارت دیگر، Delegate یک اشاره‌گر متد (Method Pointer) است که می‌تواند متدها را به عنوان پارامتر پاس دهد یا آن‌ها را به عنوان متغیر ذخیره کند. Delegates پایه و اساس رویدادها (Events) و Callbacks در C# هستند و برای پیاده‌سازی الگوهای برنامه‌نویسی تابعی استفاده می‌شوند.

انواع Delegates:
مثال‌های پایه Delegates:
using System;

// تعریف یک Delegate
public delegate void MessageHandler(string message);
public delegate int MathOperation(int a, int b);
public delegate bool Predicate<T>(T item);

public class DelegateExamples
{
    // متدهای نمونه
    public static void DisplayMessage(string msg)
    {
        Console.WriteLine($"Display: {msg}");
    }
    
    public static void LogMessage(string msg)
    {
        Console.WriteLine($"Log: [{DateTime.Now:HH:mm:ss}] {msg}");
    }
    
    public static void EmailMessage(string msg)
    {
        Console.WriteLine($"Email: Sending '{msg}' via email");
    }
    
    public static int Add(int x, int y)
    {
        return x + y;
    }
    
    public static int Multiply(int x, int y)
    {
        return x * y;
    }
    
    public static int Subtract(int x, int y)
    {
        return x - y;
    }
    
    public static void DemonstrateBasicDelegates()
    {
        Console.WriteLine("=== Basic Delegates Examples ===");
        
        // Single-cast delegate
        MessageHandler handler = DisplayMessage;
        handler("Hello World!");
        
        // تغییر متد مرجع
        handler = LogMessage;
        handler("This is a log message");
        
        // Multicast delegate
        MessageHandler multiHandler = DisplayMessage;
        multiHandler += LogMessage;
        multiHandler += EmailMessage;
        
        Console.WriteLine("\nMulticast delegate:");
        multiHandler("Important notification");
        
        // حذف متد از multicast delegate
        multiHandler -= LogMessage;
        Console.WriteLine("\nAfter removing LogMessage:");
        multiHandler("Another notification");
        
        // Math operations delegate
        Console.WriteLine("\n--- Math Operations ---");
        MathOperation operation = Add;
        Console.WriteLine($"Add: {operation(5, 3)}");
        
        operation = Multiply;
        Console.WriteLine($"Multiply: {operation(5, 3)}");
        
        operation = Subtract;
        Console.WriteLine($"Subtract: {operation(5, 3)}");
    }
}
مثال Generic Delegates (Func و Action):
public static class GenericDelegateExamples
{
    public static void DemonstrateGenericDelegates()
    {
        Console.WriteLine("\n=== Generic Delegates (Func & Action) ===");
        
        // Action - برای متدهایی که void برمی‌گردانند
        Action<string> simpleAction = msg => Console.WriteLine($"Action: {msg}");
        simpleAction("Hello from Action!");
        
        Action<string, int> complexAction = (name, age) => 
            Console.WriteLine($"Person: {name}, Age: {age}");
        complexAction("احمد محمدی", 30);
        
        // Func - برای متدهایی که مقدار برمی‌گردانند
        Func<int, int, int> addFunc = (a, b) => a + b;
        Console.WriteLine($"Add using Func: {addFunc(10, 20)}");
        
        Func<string, int> stringLengthFunc = str => str?.Length ?? 0;
        Console.WriteLine($"String length: {stringLengthFunc("Hello World")}");
        
        Func<int, bool> isEvenFunc = num => num % 2 == 0;
        Console.WriteLine($"Is 10 even: {isEvenFunc(10)}");
        Console.WriteLine($"Is 7 even: {isEvenFunc(7)}");
        
        // استفاده در collection operations
        var numbers = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        
        // فیلتر کردن با Func
        var evenNumbers = FilterNumbers(numbers, isEvenFunc);
        Console.WriteLine($"Even numbers: [{string.Join(", ", evenNumbers)}]");
        
        var greaterThanFive = FilterNumbers(numbers, x => x > 5);
        Console.WriteLine($"Numbers > 5: [{string.Join(", ", greaterThanFive)}]");
        
        // تبدیل با Func
        var squares = TransformNumbers(numbers, x => x * x);
        Console.WriteLine($"Squares: [{string.Join(", ", squares)}]");
        
        var doubled = TransformNumbers(numbers, x => x * 2);
        Console.WriteLine($"Doubled: [{string.Join(", ", doubled)}]");
    }
    
    // متد کمکی که از Func استفاده می‌کند
    public static int[] FilterNumbers(int[] numbers, Func<int, bool> predicate)
    {
        var result = new List<int>();
        foreach (int num in numbers)
        {
            if (predicate(num))
            {
                result.Add(num);
            }
        }
        return result.ToArray();
    }
    
    public static int[] TransformNumbers(int[] numbers, Func<int, int> transformer)
    {
        var result = new int[numbers.Length];
        for (int i = 0; i < numbers.Length; i++)
        {
            result[i] = transformer(numbers[i]);
        }
        return result;
    }
}
مثال کاربردی - Event System:
// سیستم رویداد با استفاده از Delegates
public class EventSystem
{
    // تعریف delegate برای رویدادهای مختلف
    public delegate void UserActionHandler(string username, string action);
    public delegate void SystemEventHandler(string eventType, DateTime timestamp, string details);
    
    // رویدادها
    public static event UserActionHandler UserAction;
    public static event SystemEventHandler SystemEvent;
    
    // متدهای فراخوانی رویداد
    public static void OnUserAction(string username, string action)
    {
        UserAction?.Invoke(username, action);
    }
    
    public static void OnSystemEvent(string eventType, string details)
    {
        SystemEvent?.Invoke(eventType, DateTime.Now, details);
    }
}

// کلاس‌های مشترک رویداد
public class Logger
{
    public void Subscribe()
    {
        EventSystem.UserAction += LogUserAction;
        EventSystem.SystemEvent += LogSystemEvent;
    }
    
    private void LogUserAction(string username, string action)
    {
        Console.WriteLine($"[LOG] User '{username}' performed action: {action}");
    }
    
    private void LogSystemEvent(string eventType, DateTime timestamp, string details)
    {
        Console.WriteLine($"[LOG] System Event: {eventType} at {timestamp:HH:mm:ss} - {details}");
    }
}

public class EmailNotifier
{
    public void Subscribe()
    {
        EventSystem.UserAction += SendUserActionEmail;
        EventSystem.SystemEvent += SendSystemEventEmail;
    }
    
    private void SendUserActionEmail(string username, string action)
    {
        if (action == "Login" || action == "Logout")
        {
            Console.WriteLine($"[EMAIL] Sending notification: User {username} {action.ToLower()}ed");
        }
    }
    
    private void SendSystemEventEmail(string eventType, DateTime timestamp, string details)
    {
        if (eventType == "Error" || eventType == "Critical")
        {
            Console.WriteLine($"[EMAIL] ALERT: {eventType} - {details}");
        }
    }
}

public class SecurityMonitor
{
    public void Subscribe()
    {
        EventSystem.UserAction += MonitorUserAction;
    }
    
    private void MonitorUserAction(string username, string action)
    {
        if (action == "Failed Login")
        {
            Console.WriteLine($"[SECURITY] WARNING: Failed login attempt by {username}");
        }
    }
}

public static void DemonstrateEventSystem()
{
    Console.WriteLine("\n=== Event System with Delegates ===");
    
    // ثبت مشترکین
    var logger = new Logger();
    var emailNotifier = new EmailNotifier();
    var securityMonitor = new SecurityMonitor();
    
    logger.Subscribe();
    emailNotifier.Subscribe();
    securityMonitor.Subscribe();
    
    // شبیه‌سازی رویدادها
    Console.WriteLine("Simulating user actions:");
    EventSystem.OnUserAction("احمد محمدی", "Login");
    EventSystem.OnUserAction("فاطمه احمدی", "View Profile");
    EventSystem.OnUserAction("هکر", "Failed Login");
    EventSystem.OnUserAction("احمد محمدی", "Logout");
    
    Console.WriteLine("\nSimulating system events:");
    EventSystem.OnSystemEvent("Info", "Application started successfully");
    EventSystem.OnSystemEvent("Warning", "High memory usage detected");
    EventSystem.OnSystemEvent("Error", "Database connection failed");
    EventSystem.OnSystemEvent("Critical", "System overload detected");
}
کاربردهای اصلی Delegates:

۶۴. Events در C# چیست؟

پاسخ:

Events (رویدادها) مکانیزمی برای ارتباط بین اشیاء هستند که به یک شیء (ناشر یا Publisher) اجازه می‌دهند تا به اشیاء دیگر (مشترکین یا Subscribers) اطلاع دهند که اتفاق خاصی رخ داده است. Events بر پایه Delegates ساخته شده‌اند و از الگوی Observer (یا Publisher-Subscriber) پیروی می‌کنند. تفاوت اصلی Event با Delegate در کنترل دسترسی و کپسوله‌سازی بهتر است.

اجزای اصلی یک Event:
مثال پایه Events:
using System;

// تعریف EventArgs سفارشی
public class PriceChangeEventArgs : EventArgs
{
    public decimal OldPrice { get; }
    public decimal NewPrice { get; }
    public decimal ChangeAmount => NewPrice - OldPrice;
    public decimal ChangePercent => OldPrice != 0 ? (ChangeAmount / OldPrice) * 100 : 0;
    
    public PriceChangeEventArgs(decimal oldPrice, decimal newPrice)
    {
        OldPrice = oldPrice;
        NewPrice = newPrice;
    }
}

// کلاس Publisher
public class Product
{
    private string _name;
    private decimal _price;
    
    // تعریف Event
    public event EventHandler<PriceChangeEventArgs> PriceChanged;
    public event EventHandler<EventArgs> ProductUpdated;
    
    public string Name
    {
        get => _name;
        set
        {
            if (_name != value)
            {
                _name = value;
                OnProductUpdated();
            }
        }
    }
    
    public decimal Price
    {
        get => _price;
        set
        {
            if (_price != value)
            {
                decimal oldPrice = _price;
                _price = value;
                OnPriceChanged(oldPrice, _price);
            }
        }
    }
    
    public Product(string name, decimal price)
    {
        _name = name;
        _price = price;
    }
    
    // متد محافظت شده برای فراخوانی Event
    protected virtual void OnPriceChanged(decimal oldPrice, decimal newPrice)
    {
        PriceChanged?.Invoke(this, new PriceChangeEventArgs(oldPrice, newPrice));
    }
    
    protected virtual void OnProductUpdated()
    {
        ProductUpdated?.Invoke(this, EventArgs.Empty);
    }
    
    public override string ToString()
    {
        return $"{Name}: ${Price:F2}";
    }
}

// کلاس‌های Subscriber
public class PriceLogger
{
    private string _loggerName;
    
    public PriceLogger(string name)
    {
        _loggerName = name;
    }
    
    public void Subscribe(Product product)
    {
        product.PriceChanged += OnPriceChanged;
        product.ProductUpdated += OnProductUpdated;
    }
    
    public void Unsubscribe(Product product)
    {
        product.PriceChanged -= OnPriceChanged;
        product.ProductUpdated -= OnProductUpdated;
    }
    
    private void OnPriceChanged(object sender, PriceChangeEventArgs e)
    {
        var product = sender as Product;
        Console.WriteLine($"[{_loggerName}] Price changed for {product?.Name}:");
        Console.WriteLine($"  Old: ${e.OldPrice:F2} → New: ${e.NewPrice:F2}");
        Console.WriteLine($"  Change: ${e.ChangeAmount:F2} ({e.ChangePercent:+0.0;-0.0}%)");
    }
    
    private void OnProductUpdated(object sender, EventArgs e)
    {
        var product = sender as Product;
        Console.WriteLine($"[{_loggerName}] Product updated: {product}");
    }
}

public class PriceAlert
{
    private decimal _threshold;
    
    public PriceAlert(decimal threshold)
    {
        _threshold = threshold;
    }
    
    public void Subscribe(Product product)
    {
        product.PriceChanged += OnPriceChanged;
    }
    
    private void OnPriceChanged(object sender, PriceChangeEventArgs e)
    {
        var product = sender as Product;
        
        if (Math.Abs(e.ChangePercent) >= _threshold)
        {
            string direction = e.ChangePercent > 0 ? "increased" : "decreased";
            Console.WriteLine($"🚨 ALERT: {product?.Name} price {direction} by {Math.Abs(e.ChangePercent):F1}%!");
        }
    }
}

public static void DemonstrateBasicEvents()
{
    Console.WriteLine("=== Basic Events Examples ===");
    
    // ایجاد محصول
    var laptop = new Product("Gaming Laptop", 1500m);
    
    // ایجاد subscribers
    var logger = new PriceLogger("Main Logger");
    var alert = new PriceAlert(10); // هشدار برای تغییرات بیش از 10%
    
    // Subscribe کردن
    logger.Subscribe(laptop);
    alert.Subscribe(laptop);
    
    Console.WriteLine($"Initial product: {laptop}");
    
    // تغییر قیمت‌ها
    Console.WriteLine("\n--- Price Changes ---");
    laptop.Price = 1400m; // کاهش 6.7%
    laptop.Price = 1200m; // کاهش 14.3% - باید alert بدهد
    laptop.Price = 1350m; // افزایش 12.5% - باید alert بدهد
    
    // تغییر نام
    Console.WriteLine("\n--- Name Change ---");
    laptop.Name = "Ultra Gaming Laptop";
    
    // Unsubscribe کردن
    Console.WriteLine("\n--- After Unsubscribing Logger ---");
    logger.Unsubscribe(laptop);
    laptop.Price = 1300m; // فقط alert باید کار کند
}
مثال پیشرفته - Order Management System:
// EventArgs classes
public class OrderEventArgs : EventArgs
{
    public Order Order { get; }
    public DateTime Timestamp { get; }
    
    public OrderEventArgs(Order order)
    {
        Order = order;
        Timestamp = DateTime.Now;
    }
}

public class OrderStatusChangedEventArgs : OrderEventArgs
{
    public OrderStatus OldStatus { get; }
    public OrderStatus NewStatus { get; }
    
    public OrderStatusChangedEventArgs(Order order, OrderStatus oldStatus, OrderStatus newStatus) 
        : base(order)
    {
        OldStatus = oldStatus;
        NewStatus = newStatus;
    }
}

// Enums and Classes
public enum OrderStatus
{
    Pending,
    Confirmed,
    Processing,
    Shipped,
    Delivered,
    Cancelled
}

public class Order
{
    public int Id { get; }
    public string CustomerName { get; }
    public decimal Amount { get; }
    public DateTime CreatedAt { get; }
    
    private OrderStatus _status;
    public OrderStatus Status
    {
        get => _status;
        private set
        {
            if (_status != value)
            {
                var oldStatus = _status;
                _status = value;
                OnStatusChanged(oldStatus, value);
            }
        }
    }
    
    // Events
    public event EventHandler<OrderEventArgs> OrderCreated;
    public event EventHandler<OrderStatusChangedEventArgs> StatusChanged;
    public event EventHandler<OrderEventArgs> OrderCancelled;
    
    public Order(int id, string customerName, decimal amount)
    {
        Id = id;
        CustomerName = customerName;
        Amount = amount;
        CreatedAt = DateTime.Now;
        _status = OrderStatus.Pending;
        
        OnOrderCreated();
    }
    
    public void UpdateStatus(OrderStatus newStatus)
    {
        if (Status == OrderStatus.Cancelled)
        {
            throw new InvalidOperationException("Cannot update status of cancelled order");
        }
        
        Status = newStatus;
    }
    
    public void Cancel()
    {
        if (Status == OrderStatus.Delivered)
        {
            throw new InvalidOperationException("Cannot cancel delivered order");
        }
        
        Status = OrderStatus.Cancelled;
        OnOrderCancelled();
    }
    
    protected virtual void OnOrderCreated()
    {
        OrderCreated?.Invoke(this, new OrderEventArgs(this));
    }
    
    protected virtual void OnStatusChanged(OrderStatus oldStatus, OrderStatus newStatus)
    {
        StatusChanged?.Invoke(this, new OrderStatusChangedEventArgs(this, oldStatus, newStatus));
    }
    
    protected virtual void OnOrderCancelled()
    {
        OrderCancelled?.Invoke(this, new OrderEventArgs(this));
    }
    
    public override string ToString()
    {
        return $"Order #{Id}: {CustomerName} - ${Amount:F2} ({Status})";
    }
}

// Service classes (Subscribers)
public class EmailService
{
    public void Subscribe(Order order)
    {
        order.OrderCreated += OnOrderCreated;
        order.StatusChanged += OnStatusChanged;
        order.OrderCancelled += OnOrderCancelled;
    }
    
    private void OnOrderCreated(object sender, OrderEventArgs e)
    {
        Console.WriteLine($"📧 Email: Order confirmation sent to {e.Order.CustomerName}");
    }
    
    private void OnStatusChanged(object sender, OrderStatusChangedEventArgs e)
    {
        string message = e.NewStatus switch
        {
            OrderStatus.Confirmed => "Order confirmed",
            OrderStatus.Processing => "Order is being processed",
            OrderStatus.Shipped => "Order has been shipped",
            OrderStatus.Delivered => "Order delivered successfully",
            _ => $"Order status updated to {e.NewStatus}"
        };
        
        Console.WriteLine($"📧 Email: {message} - Order #{e.Order.Id}");
    }
    
    private void OnOrderCancelled(object sender, OrderEventArgs e)
    {
        Console.WriteLine($"📧 Email: Order cancellation confirmation sent to {e.Order.CustomerName}");
    }
}

public class InventoryService
{
    public void Subscribe(Order order)
    {
        order.OrderCreated += OnOrderCreated;
        order.StatusChanged += OnStatusChanged;
        order.OrderCancelled += OnOrderCancelled;
    }
    
    private void OnOrderCreated(object sender, OrderEventArgs e)
    {
        Console.WriteLine($"📦 Inventory: Reserved items for Order #{e.Order.Id}");
    }
    
    private void OnStatusChanged(object sender, OrderStatusChangedEventArgs e)
    {
        if (e.NewStatus == OrderStatus.Delivered)
        {
            Console.WriteLine($"📦 Inventory: Items confirmed as delivered for Order #{e.Order.Id}");
        }
    }
    
    private void OnOrderCancelled(object sender, OrderEventArgs e)
    {
        Console.WriteLine($"📦 Inventory: Released reserved items for Order #{e.Order.Id}");
    }
}

public class AuditService
{
    public void Subscribe(Order order)
    {
        order.OrderCreated += LogEvent;
        order.StatusChanged += OnStatusChanged;
        order.OrderCancelled += LogEvent;
    }
    
    private void LogEvent(object sender, OrderEventArgs e)
    {
        Console.WriteLine($"📝 Audit: [{e.Timestamp:HH:mm:ss}] Event logged for {e.Order}");
    }
    
    private void OnStatusChanged(object sender, OrderStatusChangedEventArgs e)
    {
        Console.WriteLine($"📝 Audit: [{e.Timestamp:HH:mm:ss}] Status changed from {e.OldStatus} to {e.NewStatus} for Order #{e.Order.Id}");
    }
}

public static void DemonstrateOrderManagement()
{
    Console.WriteLine("\n=== Order Management System Events ===");
    
    // ایجاد سرویس‌ها
    var emailService = new EmailService();
    var inventoryService = new InventoryService();
    var auditService = new AuditService();
    
    // ایجاد سفارش
    var order = new Order(1001, "احمد محمدی", 299.99m);
    
    // Subscribe کردن سرویس‌ها
    emailService.Subscribe(order);
    inventoryService.Subscribe(order);
    auditService.Subscribe(order);
    
    Console.WriteLine($"Created: {order}");
    
    // شبیه‌سازی lifecycle سفارش
    Console.WriteLine("\n--- Order Lifecycle ---");
    
    System.Threading.Thread.Sleep(1000);
    order.UpdateStatus(OrderStatus.Confirmed);
    
    System.Threading.Thread.Sleep(1000);
    order.UpdateStatus(OrderStatus.Processing);
    
    System.Threading.Thread.Sleep(1000);
    order.UpdateStatus(OrderStatus.Shipped);
    
    System.Threading.Thread.Sleep(1000);
    order.UpdateStatus(OrderStatus.Delivered);
    
    // تست cancellation
    Console.WriteLine("\n--- Testing Cancellation ---");
    var order2 = new Order(1002, "فاطمه احمدی", 150.00m);
    
    emailService.Subscribe(order2);
    inventoryService.Subscribe(order2);
    auditService.Subscribe(order2);
    
    System.Threading.Thread.Sleep(500);
    order2.UpdateStatus(OrderStatus.Confirmed);
    
    System.Threading.Thread.Sleep(500);
    order2.Cancel();
}
تفاوت Events و Delegates:

۶۵. Generics در C# چیست؟

پاسخ:

Generics (انواع عمومی) در C# به شما اجازه می‌دهند تا کلاس‌ها، متدها، interfaces و delegates را به گونه‌ای تعریف کنید که با انواع داده‌ای مختلفی کار کنند، بدون اینکه نیاز به تعریف مجدد کد برای هر نوع داده‌ای باشد. این کار با استفاده از پارامترهای نوع (Type Parameters) انجام می‌شود. Generics نوع ایمنی، عملکرد بهتر و قابلیت استفاده مجدد کد را فراهم می‌کنند.

مزایای Generics:
مثال Generic Classes:
using System;
using System.Collections.Generic;

// Generic class ساده
public class MyGenericList<T>
{
    private T[] _items;
    private int _count;
    
    public MyGenericList(int capacity = 10)
    {
        _items = new T[capacity];
        _count = 0;
    }
    
    public void Add(T item)
    {
        if (_count >= _items.Length)
        {
            Resize();
        }
        _items[_count++] = item;
    }
    
    public T Get(int index)
    {
        if (index < 0 || index >= _count)
            throw new IndexOutOfRangeException();
        return _items[index];
    }
    
    public bool Remove(T item)
    {
        for (int i = 0; i < _count; i++)
        {
            if (EqualityComparer<T>.Default.Equals(_items[i], item))
            {
                // Shift elements
                for (int j = i; j < _count - 1; j++)
                {
                    _items[j] = _items[j + 1];
                }
                _count--;
                return true;
            }
        }
        return false;
    }
    
    public int Count => _count;
    
    public bool Contains(T item)
    {
        for (int i = 0; i < _count; i++)
        {
            if (EqualityComparer<T>.Default.Equals(_items[i], item))
                return true;
        }
        return false;
    }
    
    private void Resize()
    {
        T[] newArray = new T[_items.Length * 2];
        Array.Copy(_items, newArray, _count);
        _items = newArray;
    }
    
    public IEnumerable<T> GetAll()
    {
        for (int i = 0; i < _count; i++)
        {
            yield return _items[i];
        }
    }
}

// Generic class با multiple type parameters
public class KeyValuePair<TKey, TValue>
{
    public TKey Key { get; set; }
    public TValue Value { get; set; }
    
    public KeyValuePair(TKey key, TValue value)
    {
        Key = key;
        Value = value;
    }
    
    public override string ToString()
    {
        return $"[{Key}: {Value}]";
    }
}

public class MyGenericDictionary<TKey, TValue>
{
    private List<KeyValuePair<TKey, TValue>> _items;
    
    public MyGenericDictionary()
    {
        _items = new List<KeyValuePair<TKey, TValue>>();
    }
    
    public void Add(TKey key, TValue value)
    {
        if (ContainsKey(key))
            throw new ArgumentException($"Key '{key}' already exists");
            
        _items.Add(new KeyValuePair<TKey, TValue>(key, value));
    }
    
    public TValue Get(TKey key)
    {
        foreach (var item in _items)
        {
            if (EqualityComparer<TKey>.Default.Equals(item.Key, key))
                return item.Value;
        }
        throw new KeyNotFoundException($"Key '{key}' not found");
    }
    
    public bool ContainsKey(TKey key)
    {
        foreach (var item in _items)
        {
            if (EqualityComparer<TKey>.Default.Equals(item.Key, key))
                return true;
        }
        return false;
    }
    
    public int Count => _items.Count;
    
    public IEnumerable<KeyValuePair<TKey, TValue>> GetAll()
    {
        return _items;
    }
}

public static void DemonstrateGenericClasses()
{
    Console.WriteLine("=== Generic Classes Examples ===");
    
    // Generic List با int
    var intList = new MyGenericList<int>();
    intList.Add(10);
    intList.Add(20);
    intList.Add(30);
    
    Console.WriteLine($"Int List Count: {intList.Count}");
    Console.WriteLine($"Contains 20: {intList.Contains(20)}");
    Console.WriteLine($"Items: [{string.Join(", ", intList.GetAll())}]");
    
    // Generic List با string
    var stringList = new MyGenericList<string>();
    stringList.Add("Hello");
    stringList.Add("World");
    stringList.Add("Generics");
    
    Console.WriteLine($"\nString List Count: {stringList.Count}");
    Console.WriteLine($"Items: [{string.Join(", ", stringList.GetAll())}]");
    
    // Generic Dictionary
    var dictionary = new MyGenericDictionary<string, int>();
    dictionary.Add("Apple", 5);
    dictionary.Add("Banana", 3);
    dictionary.Add("Orange", 8);
    
    Console.WriteLine($"\nDictionary Count: {dictionary.Count}");
    Console.WriteLine($"Apple count: {dictionary.Get("Apple")}");
    Console.WriteLine("All items:");
    foreach (var item in dictionary.GetAll())
    {
        Console.WriteLine($"  {item}");
    }
}
مثال Generic Methods:
public static class GenericMethods
{
    // Generic method ساده
    public static void Swap<T>(ref T a, ref T b)
    {
        T temp = a;
        a = b;
        b = temp;
    }
    
    // Generic method با return value
    public static T GetDefault<T>()
    {
        return default(T);
    }
    
    // Generic method با multiple parameters
    public static TResult Transform<TInput, TResult>(TInput input, Func<TInput, TResult> transformer)
    {
        return transformer(input);
    }
    
    // Generic method برای array operations
    public static T[] CreateArray<T>(int size, T defaultValue)
    {
        T[] array = new T[size];
        for (int i = 0; i < size; i++)
        {
            array[i] = defaultValue;
        }
        return array;
    }
    
    // Generic method برای finding maximum
    public static T FindMax<T>(T[] array) where T : IComparable<T>
    {
        if (array == null || array.Length == 0)
            throw new ArgumentException("Array cannot be null or empty");
            
        T max = array[0];
        for (int i = 1; i < array.Length; i++)
        {
            if (array[i].CompareTo(max) > 0)
                max = array[i];
        }
        return max;
    }
    
    // Generic method برای filtering
    public static List<T> Filter<T>(IEnumerable<T> source, Func<T, bool> predicate)
    {
        var result = new List<T>();
        foreach (T item in source)
        {
            if (predicate(item))
                result.Add(item);
        }
        return result;
    }
    
    // Generic method برای mapping
    public static List<TResult> Map<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> mapper)
    {
        var result = new List<TResult>();
        foreach (TSource item in source)
        {
            result.Add(mapper(item));
        }
        return result;
    }
}

public static void DemonstrateGenericMethods()
{
    Console.WriteLine("\n=== Generic Methods Examples ===");
    
    // Swap method
    int x = 10, y = 20;
    Console.WriteLine($"Before swap: x={x}, y={y}");
    GenericMethods.Swap(ref x, ref y);
    Console.WriteLine($"After swap: x={x}, y={y}");
    
    string s1 = "Hello", s2 = "World";
    Console.WriteLine($"Before swap: s1={s1}, s2={s2}");
    GenericMethods.Swap(ref s1, ref s2);
    Console.WriteLine($"After swap: s1={s1}, s2={s2}");
    
    // Default values
    Console.WriteLine($"\nDefault int: {GenericMethods.GetDefault<int>()}");
    Console.WriteLine($"Default string: '{GenericMethods.GetDefault<string>()}'");
    Console.WriteLine($"Default bool: {GenericMethods.GetDefault<bool>()}");
    
    // Transform method
    string numberStr = "42";
    int number = GenericMethods.Transform(numberStr, s => int.Parse(s));
    Console.WriteLine($"Transformed '{numberStr}' to {number}");
    
    double doubleNum = GenericMethods.Transform(number, n => n * 1.5);
    Console.WriteLine($"Transformed {number} to {doubleNum}");
    
    // Array creation
    var intArray = GenericMethods.CreateArray(5, 100);
    Console.WriteLine($"Created int array: [{string.Join(", ", intArray)}]");
    
    var stringArray = GenericMethods.CreateArray(3, "Default");
    Console.WriteLine($"Created string array: [{string.Join(", ", stringArray)}]");
    
    // Find maximum
    int[] numbers = { 5, 2, 8, 1, 9, 3 };
    int maxNumber = GenericMethods.FindMax(numbers);
    Console.WriteLine($"Max number in [{string.Join(", ", numbers)}]: {maxNumber}");
    
    string[] words = { "apple", "zebra", "banana", "orange" };
    string maxWord = GenericMethods.FindMax(words);
    Console.WriteLine($"Max word in [{string.Join(", ", words)}]: {maxWord}");
    
    // Filter and Map
    var evenNumbers = GenericMethods.Filter(numbers, n => n % 2 == 0);
    Console.WriteLine($"Even numbers: [{string.Join(", ", evenNumbers)}]");
    
    var squares = GenericMethods.Map(numbers, n => n * n);
    Console.WriteLine($"Squares: [{string.Join(", ", squares)}]");
    
    var upperWords = GenericMethods.Map(words, w => w.ToUpper());
    Console.WriteLine($"Upper words: [{string.Join(", ", upperWords)}]");
}
مثال Generic Interfaces:
// Generic interface
public interface IRepository<T> where T : class
{
    void Add(T entity);
    T GetById(int id);
    IEnumerable<T> GetAll();
    bool Update(T entity);
    bool Delete(int id);
    int Count { get; }
}

// Entity classes
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    
    public override string ToString()
    {
        return $"User {Id}: {Name} ({Email})";
    }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    
    public override string ToString()
    {
        return $"Product {Id}: {Name} - ${Price:F2}";
    }
}

// Generic repository implementation
public class InMemoryRepository<T> : IRepository<T> where T : class
{
    private readonly List<T> _entities;
    private readonly Func<T, int> _idSelector;
    private int _nextId;
    
    public InMemoryRepository(Func<T, int> idSelector)
    {
        _entities = new List<T>();
        _idSelector = idSelector;
        _nextId = 1;
    }
    
    public void Add(T entity)
    {
        // برای سادگی، فرض می‌کنیم Id را خودمان set می‌کنیم
        SetId(entity, _nextId++);
        _entities.Add(entity);
    }
    
    public T GetById(int id)
    {
        return _entities.FirstOrDefault(e => _idSelector(e) == id);
    }
    
    public IEnumerable<T> GetAll()
    {
        return _entities.ToList();
    }
    
    public bool Update(T entity)
    {
        var existing = GetById(_idSelector(entity));
        if (existing != null)
        {
            var index = _entities.IndexOf(existing);
            _entities[index] = entity;
            return true;
        }
        return false;
    }
    
    public bool Delete(int id)
    {
        var entity = GetById(id);
        if (entity != null)
        {
            _entities.Remove(entity);
            return true;
        }
        return false;
    }
    
    public int Count => _entities.Count;
    
    private void SetId(T entity, int id)
    {
        // ساده‌سازی شده - در واقعیت باید از reflection استفاده کرد
        if (entity is User user)
            user.Id = id;
        else if (entity is Product product)
            product.Id = id;
    }
}

public static void DemonstrateGenericInterfaces()
{
    Console.WriteLine("\n=== Generic Interfaces Examples ===");
    
    // User repository
    var userRepo = new InMemoryRepository<User>(u => u.Id);
    
    userRepo.Add(new User { Name = "احمد محمدی", Email = "[email protected]" });
    userRepo.Add(new User { Name = "فاطمه احمدی", Email = "[email protected]" });
    userRepo.Add(new User { Name = "علی رضایی", Email = "[email protected]" });
    
    Console.WriteLine($"User repository count: {userRepo.Count}");
    Console.WriteLine("All users:");
    foreach (var user in userRepo.GetAll())
    {
        Console.WriteLine($"  {user}");
    }
    
    var user2 = userRepo.GetById(2);
    Console.WriteLine($"User with ID 2: {user2}");
    
    // Product repository
    var productRepo = new InMemoryRepository<Product>(p => p.Id);
    
    productRepo.Add(new Product { Name = "لپ‌تاپ", Price = 1500m });
    productRepo.Add(new Product { Name = "موس", Price = 25m });
    productRepo.Add(new Product { Name = "کیبورد", Price = 75m });
    
    Console.WriteLine($"\nProduct repository count: {productRepo.Count}");
    Console.WriteLine("All products:");
    foreach (var product in productRepo.GetAll())
    {
        Console.WriteLine($"  {product}");
    }
    
    // Update product
    var laptop = productRepo.GetById(1);
    if (laptop != null)
    {
        laptop.Price = 1400m;
        productRepo.Update(laptop);
        Console.WriteLine($"Updated laptop price: {laptop}");
    }
    
    // Delete product
    bool deleted = productRepo.Delete(2);
    Console.WriteLine($"Deleted mouse: {deleted}");
    Console.WriteLine($"Remaining products: {productRepo.Count}");
}
بهترین شیوه‌های استفاده از Generics:

۶۶. Attributes در C# چیست؟

پاسخ:

Attributes (صفات) در C# راهی برای افزودن فراداده (metadata) یا اطلاعات توصیفی به کد شما هستند. این فراداده می‌تواند در زمان کامپایل یا در زمان اجرا (با استفاده از Reflection) توسط برنامه‌ها یا ابزارهای دیگر خوانده شود. Attributes به صورت کلاس‌هایی تعریف می‌شوند که از System.Attribute ارث‌بری می‌کنند و با قرار دادن آن‌ها در براکت ([]) قبل از یک عنصر کد اعمال می‌شوند.

کاربردهای اصلی Attributes:
مثال تعریف Attribute سفارشی:
using System;
using System.Reflection;

// تعریف یک Attribute سفارشی
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class DeveloperInfoAttribute : Attribute
{
    public string Name { get; set; }
    public string Date { get; set; }
    public string Version { get; set; }

    public DeveloperInfoAttribute(string name, string date)
    {
        Name = name;
        Date = date;
    }
}

// Attribute برای مستندسازی API
[AttributeUsage(AttributeTargets.Method)]
public class ApiDocumentationAttribute : Attribute
{
    public string Description { get; set; }
    public string Example { get; set; }
    public bool IsDeprecated { get; set; }

    public ApiDocumentationAttribute(string description)
    {
        Description = description;
    }
}

// استفاده از Attributes
[DeveloperInfo("احمد محمدی", "2023-01-15", Version = "1.0")]
[DeveloperInfo("فاطمه احمدی", "2023-02-20", Version = "1.1")]
public class MyClassWithAttributes
{
    [DeveloperInfo("علی رضایی", "2023-03-01")]
    [ApiDocumentation("محاسبه مجموع دو عدد", Example = "Add(5, 3) returns 8")]
    public int Add(int a, int b)
    {
        return a + b;
    }

    [ApiDocumentation("تبدیل رشته به حروف بزرگ", IsDeprecated = true)]
    public string ToUpper(string text)
    {
        return text?.ToUpper();
    }
}

public class AttributeExample
{
    public static void Main(string[] args)
    {
        Console.WriteLine("=== Reading Attributes with Reflection ===");
        
        // خواندن Attributes کلاس
        Type type = typeof(MyClassWithAttributes);
        var classAttributes = type.GetCustomAttributes(typeof(DeveloperInfoAttribute), false);

        Console.WriteLine("Class Developers:");
        foreach (DeveloperInfoAttribute attr in classAttributes)
        {
            Console.WriteLine($"  Name: {attr.Name}, Date: {attr.Date}, Version: {attr.Version}");
        }

        // خواندن Attributes متدها
        var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
        
        foreach (var method in methods)
        {
            Console.WriteLine($"\nMethod: {method.Name}");
            
            // Developer Info
            var devAttrs = method.GetCustomAttributes(typeof(DeveloperInfoAttribute), false);
            foreach (DeveloperInfoAttribute attr in devAttrs)
            {
                Console.WriteLine($"  Developer: {attr.Name} ({attr.Date})");
            }
            
            // API Documentation
            var docAttrs = method.GetCustomAttributes(typeof(ApiDocumentationAttribute), false);
            foreach (ApiDocumentationAttribute attr in docAttrs)
            {
                Console.WriteLine($"  Description: {attr.Description}");
                if (!string.IsNullOrEmpty(attr.Example))
                    Console.WriteLine($"  Example: {attr.Example}");
                if (attr.IsDeprecated)
                    Console.WriteLine($"  ⚠️ DEPRECATED");
            }
        }
    }
}
مثال Validation Attributes:
using System;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using System.Linq;

// کلاس مدل با Validation Attributes
public class User
{
    [Required(ErrorMessage = "نام کاربری الزامی است")]
    [StringLength(50, MinimumLength = 3, ErrorMessage = "نام کاربری باید بین 3 تا 50 کاراکتر باشد")]
    public string Username { get; set; }

    [Required(ErrorMessage = "ایمیل الزامی است")]
    [EmailAddress(ErrorMessage = "فرمت ایمیل صحیح نیست")]
    public string Email { get; set; }

    [Range(18, 120, ErrorMessage = "سن باید بین 18 تا 120 سال باشد")]
    public int Age { get; set; }

    [Phone(ErrorMessage = "فرمت شماره تلفن صحیح نیست")]
    public string PhoneNumber { get; set; }

    [Url(ErrorMessage = "فرمت URL صحیح نیست")]
    public string Website { get; set; }
}

// Custom Validation Attribute
public class PersianNameAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        if (value == null) return true; // اگر Required نیست
        
        string name = value.ToString();
        // بررسی ساده برای نام فارسی (فقط حروف فارسی و فاصله)
        return name.All(c => char.IsWhiteSpace(c) || (c >= 'آ' && c <= 'ی'));
    }

    public override string FormatErrorMessage(string name)
    {
        return $"{name} باید فقط شامل حروف فارسی باشد";
    }
}

public class Person
{
    [Required(ErrorMessage = "نام الزامی است")]
    [PersianName]
    public string Name { get; set; }

    [Required(ErrorMessage = "نام خانوادگی الزامی است")]
    [PersianName]
    public string LastName { get; set; }
}

public static class ValidationHelper
{
    public static List<string> ValidateObject(object obj)
    {
        var context = new ValidationContext(obj);
        var results = new List<ValidationResult>();
        var errors = new List<string>();

        bool isValid = Validator.TryValidateObject(obj, context, results, true);

        if (!isValid)
        {
            errors.AddRange(results.Select(r => r.ErrorMessage));
        }

        return errors;
    }
}

public static void DemonstrateValidationAttributes()
{
    Console.WriteLine("\n=== Validation Attributes Examples ===");
    
    // تست User validation
    var user1 = new User
    {
        Username = "ab", // خیلی کوتاه
        Email = "invalid-email", // فرمت نادرست
        Age = 15, // خیلی کم
        PhoneNumber = "123", // فرمت نادرست
        Website = "not-a-url" // فرمت نادرست
    };

    var errors1 = ValidationHelper.ValidateObject(user1);
    Console.WriteLine("User1 validation errors:");
    foreach (var error in errors1)
    {
        Console.WriteLine($"  - {error}");
    }

    // تست User صحیح
    var user2 = new User
    {
        Username = "ahmad_mohammadi",
        Email = "[email protected]",
        Age = 30,
        PhoneNumber = "+98-912-345-6789",
        Website = "https://example.com"
    };

    var errors2 = ValidationHelper.ValidateObject(user2);
    Console.WriteLine($"\nUser2 validation errors: {errors2.Count}");

    // تست Custom Attribute
    var person1 = new Person
    {
        Name = "Ahmad", // نام انگلیسی
        LastName = "محمدی"
    };

    var errors3 = ValidationHelper.ValidateObject(person1);
    Console.WriteLine("\nPerson1 validation errors:");
    foreach (var error in errors3)
    {
        Console.WriteLine($"  - {error}");
    }

    var person2 = new Person
    {
        Name = "احمد",
        LastName = "محمدی"
    };

    var errors4 = ValidationHelper.ValidateObject(person2);
    Console.WriteLine($"\nPerson2 validation errors: {errors4.Count}");
}
مثال Serialization Attributes:
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

// کلاس با Serialization Attributes
public class Product
{
    [JsonPropertyName("id")]
    public int Id { get; set; }

    [JsonPropertyName("product_name")]
    public string Name { get; set; }

    [JsonPropertyName("price")]
    [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
    public decimal Price { get; set; }

    [JsonPropertyName("created_date")]
    public DateTime CreatedDate { get; set; }

    [JsonIgnore]
    public string InternalCode { get; set; }

    [JsonPropertyName("is_available")]
    public bool IsAvailable { get; set; }

    [JsonPropertyName("tags")]
    public List<string> Tags { get; set; } = new List<string>();

    // Property که فقط در serialization شرکت می‌کند
    [JsonPropertyName("display_name")]
    public string DisplayName => $"{Name} (${Price:F2})";
}

public static void DemonstrateSerializationAttributes()
{
    Console.WriteLine("\n=== Serialization Attributes Examples ===");
    
    var product = new Product
    {
        Id = 1,
        Name = "لپ‌تاپ گیمینگ",
        Price = 1500.99m,
        CreatedDate = DateTime.Now,
        InternalCode = "INTERNAL-001", // این فیلد serialize نمی‌شود
        IsAvailable = true,
        Tags = new List<string> { "gaming", "laptop", "electronics" }
    };

    // Serialize to JSON
    var options = new JsonSerializerOptions
    {
        WriteIndented = true,
        Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
    };

    string json = JsonSerializer.Serialize(product, options);
    Console.WriteLine("Serialized JSON:");
    Console.WriteLine(json);

    // Deserialize from JSON
    string jsonInput = @"{
        ""id"": 2,
        ""product_name"": ""موس گیمینگ"",
        ""price"": ""25.50"",
        ""created_date"": ""2023-12-01T10:30:00"",
        ""is_available"": false,
        ""tags"": [""gaming"", ""mouse"", ""accessories""]
    }";

    var deserializedProduct = JsonSerializer.Deserialize<Product>(jsonInput, options);
    Console.WriteLine("\nDeserialized Product:");
    Console.WriteLine($"ID: {deserializedProduct.Id}");
    Console.WriteLine($"Name: {deserializedProduct.Name}");
    Console.WriteLine($"Price: {deserializedProduct.Price:C}");
    Console.WriteLine($"Available: {deserializedProduct.IsAvailable}");
    Console.WriteLine($"Tags: [{string.Join(", ", deserializedProduct.Tags)}]");
    Console.WriteLine($"Display Name: {deserializedProduct.DisplayName}");
    Console.WriteLine($"Internal Code: '{deserializedProduct.InternalCode}' (should be null)");
}
بهترین شیوه‌های استفاده از Attributes:

۶۷. Reflection در C# چیست؟

پاسخ:

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

کاربردهای اصلی Reflection:
مثال پایه Reflection:
using System;
using System.Reflection;

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Major { get; set; }
    private double _gpa;

    public Student() { }

    public Student(int id, string name, string major)
    {
        Id = id;
        Name = name;
        Major = major;
    }

    public void SetGPA(double gpa)
    {
        if (gpa >= 0 && gpa <= 4.0)
            _gpa = gpa;
        else
            throw new ArgumentException("GPA must be between 0 and 4.0");
    }

    public double GetGPA()
    {
        return _gpa;
    }

    public void DisplayInfo()
    {
        Console.WriteLine($"Student: {Name} (ID: {Id}, Major: {Major}, GPA: {_gpa:F2})");
    }

    private void PrivateMethod()
    {
        Console.WriteLine("This is a private method");
    }
}

public static void DemonstrateBasicReflection()
{
    Console.WriteLine("=== Basic Reflection Examples ===");
    
    // 1. دریافت نوع یک کلاس
    Type studentType = typeof(Student);
    Console.WriteLine($"Type Name: {studentType.Name}");
    Console.WriteLine($"Full Name: {studentType.FullName}");
    Console.WriteLine($"Assembly: {studentType.Assembly.GetName().Name}");
    Console.WriteLine($"Is Class: {studentType.IsClass}");
    Console.WriteLine($"Is Public: {studentType.IsPublic}");

    // 2. دریافت اطلاعات Properties
    Console.WriteLine("\nProperties:");
    PropertyInfo[] properties = studentType.GetProperties();
    foreach (PropertyInfo prop in properties)
    {
        Console.WriteLine($"  {prop.PropertyType.Name} {prop.Name} (CanRead: {prop.CanRead}, CanWrite: {prop.CanWrite})");
    }

    // 3. دریافت اطلاعات Fields
    Console.WriteLine("\nFields:");
    FieldInfo[] fields = studentType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
    foreach (FieldInfo field in fields)
    {
        Console.WriteLine($"  {field.FieldType.Name} {field.Name} (IsPrivate: {field.IsPrivate})");
    }

    // 4. دریافت اطلاعات Methods
    Console.WriteLine("\nMethods:");
    MethodInfo[] methods = studentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
    foreach (MethodInfo method in methods)
    {
        var parameters = method.GetParameters();
        var paramTypes = string.Join(", ", Array.ConvertAll(parameters, p => p.ParameterType.Name));
        Console.WriteLine($"  {method.ReturnType.Name} {method.Name}({paramTypes}) (IsPublic: {method.IsPublic})");
    }

    // 5. دریافت اطلاعات Constructors
    Console.WriteLine("\nConstructors:");
    ConstructorInfo[] constructors = studentType.GetConstructors();
    foreach (ConstructorInfo ctor in constructors)
    {
        var parameters = ctor.GetParameters();
        var paramTypes = string.Join(", ", Array.ConvertAll(parameters, p => $"{p.ParameterType.Name} {p.Name}"));
        Console.WriteLine($"  {ctor.Name}({paramTypes})");
    }
}
مثال Dynamic Object Creation:
public static void DemonstrateDynamicCreation()
{
    Console.WriteLine("\n=== Dynamic Object Creation ===");
    
    Type studentType = typeof(Student);
    
    // 1. ایجاد نمونه با سازنده پیش‌فرض
    object student1 = Activator.CreateInstance(studentType);
    Console.WriteLine($"Created instance: {student1.GetType().Name}");
    
    // 2. ایجاد نمونه با سازنده پارامتردار
    object student2 = Activator.CreateInstance(studentType, 1, "احمد محمدی", "Computer Science");
    Console.WriteLine($"Created instance with parameters: {student2}");
    
    // 3. تنظیم Properties با Reflection
    PropertyInfo nameProperty = studentType.GetProperty("Name");
    PropertyInfo idProperty = studentType.GetProperty("Id");
    PropertyInfo majorProperty = studentType.GetProperty("Major");
    
    nameProperty.SetValue(student1, "فاطمه احمدی");
    idProperty.SetValue(student1, 2);
    majorProperty.SetValue(student1, "Mathematics");
    
    // 4. خواندن Properties با Reflection
    string name = (string)nameProperty.GetValue(student1);
    int id = (int)idProperty.GetValue(student1);
    string major = (string)majorProperty.GetValue(student1);
    
    Console.WriteLine($"Student1 - ID: {id}, Name: {name}, Major: {major}");
    
    // 5. فراخوانی متد با Reflection
    MethodInfo setGpaMethod = studentType.GetMethod("SetGPA");
    MethodInfo displayMethod = studentType.GetMethod("DisplayInfo");
    
    setGpaMethod.Invoke(student1, new object[] { 3.8 });
    setGpaMethod.Invoke(student2, new object[] { 3.5 });
    
    Console.WriteLine("\nDisplaying student info using Reflection:");
    displayMethod.Invoke(student1, null);
    displayMethod.Invoke(student2, null);
    
    // 6. دسترسی به متد private
    MethodInfo privateMethod = studentType.GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
    Console.WriteLine("\nCalling private method:");
    privateMethod.Invoke(student1, null);
    
    // 7. دسترسی به فیلد private
    FieldInfo gpaField = studentType.GetField("_gpa", BindingFlags.NonPublic | BindingFlags.Instance);
    double gpa = (double)gpaField.GetValue(student1);
    Console.WriteLine($"Private GPA field value: {gpa}");
}
مثال Generic Type Handling:
public class GenericClass<T>
{
    public T Value { get; set; }
    
    public GenericClass(T value)
    {
        Value = value;
    }
    
    public void DisplayValue()
    {
        Console.WriteLine($"Value: {Value} (Type: {typeof(T).Name})");
    }
    
    public TResult Transform<TResult>(Func<T, TResult> transformer)
    {
        return transformer(Value);
    }
}

public static void DemonstrateGenericReflection()
{
    Console.WriteLine("\n=== Generic Type Reflection ===");
    
    // 1. کار با Generic Type Definition
    Type genericTypeDefinition = typeof(GenericClass<>);
    Console.WriteLine($"Generic Type Definition: {genericTypeDefinition.Name}");
    Console.WriteLine($"Is Generic Type Definition: {genericTypeDefinition.IsGenericTypeDefinition}");
    
    // 2. ایجاد Generic Type با نوع مشخص
    Type stringGenericType = genericTypeDefinition.MakeGenericType(typeof(string));
    Type intGenericType = genericTypeDefinition.MakeGenericType(typeof(int));
    
    Console.WriteLine($"String Generic Type: {stringGenericType.Name}");
    Console.WriteLine($"Int Generic Type: {intGenericType.Name}");
    
    // 3. ایجاد نمونه از Generic Type
    object stringInstance = Activator.CreateInstance(stringGenericType, "Hello Generics!");
    object intInstance = Activator.CreateInstance(intGenericType, 42);
    
    // 4. فراخوانی متد Generic
    MethodInfo displayMethod = stringGenericType.GetMethod("DisplayValue");
    displayMethod.Invoke(stringInstance, null);
    displayMethod.Invoke(intInstance, null);
    
    // 5. کار با Generic Method
    MethodInfo transformMethod = stringGenericType.GetMethod("Transform");
    MethodInfo specificTransformMethod = transformMethod.MakeGenericMethod(typeof(int));
    
    // ایجاد یک Func<string, int> برای تبدیل string به length
    Func<string, int> lengthTransformer = s => s.Length;
    
    object result = specificTransformMethod.Invoke(stringInstance, new object[] { lengthTransformer });
    Console.WriteLine($"Transform result: {result}");
    
    // 6. بررسی Generic Type Arguments
    Type[] genericArguments = stringGenericType.GetGenericArguments();
    Console.WriteLine($"Generic Arguments for string instance: {string.Join(", ", Array.ConvertAll(genericArguments, t => t.Name))}");
}
مثال Attribute Reading:
[Obsolete("Use NewCalculator instead", false)]
public class Calculator
{
    [System.ComponentModel.Description("Adds two integers")]
    public int Add(int a, int b)
    {
        return a + b;
    }
    
    [System.ComponentModel.Description("Multiplies two integers")]
    [Obsolete("Use AdvancedMultiply instead")]
    public int Multiply(int a, int b)
    {
        return a * b;
    }
}

public static void DemonstrateAttributeReflection()
{
    Console.WriteLine("\n=== Attribute Reflection ===");
    
    Type calculatorType = typeof(Calculator);
    
    // 1. خواندن Attributes کلاس
    object[] classAttributes = calculatorType.GetCustomAttributes(false);
    Console.WriteLine("Class Attributes:");
    foreach (Attribute attr in classAttributes)
    {
        if (attr is ObsoleteAttribute obsoleteAttr)
        {
            Console.WriteLine($"  Obsolete: {obsoleteAttr.Message} (IsError: {obsoleteAttr.IsError})");
        }
    }
    
    // 2. خواندن Attributes متدها
    MethodInfo[] methods = calculatorType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
    
    foreach (MethodInfo method in methods)
    {
        Console.WriteLine($"\nMethod: {method.Name}");
        
        // Description Attribute
        var descriptionAttrs = method.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false);
        foreach (System.ComponentModel.DescriptionAttribute desc in descriptionAttrs)
        {
            Console.WriteLine($"  Description: {desc.Description}");
        }
        
        // Obsolete Attribute
        var obsoleteAttrs = method.GetCustomAttributes(typeof(ObsoleteAttribute), false);
        foreach (ObsoleteAttribute obs in obsoleteAttrs)
        {
            Console.WriteLine($"  ⚠️ Obsolete: {obs.Message}");
        }
        
        // بررسی وجود Attribute خاص
        bool hasObsolete = method.IsDefined(typeof(ObsoleteAttribute), false);
        Console.WriteLine($"  Has Obsolete Attribute: {hasObsolete}");
    }
}
نکات مهم Reflection:

۶۸. Async/Await در C# چیست؟

پاسخ:

Async/Await الگویی برای برنامه‌نویسی ناهمزمان (Asynchronous Programming) در C# است که در .NET 4.5 معرفی شد. این الگو به شما اجازه می‌دهد تا عملیات طولانی‌مدت را بدون مسدود کردن thread اصلی اجرا کنید و در عین حال کد را به شکل همزمان (synchronous) بنویسید که خواناتر و قابل فهم‌تر است.

مزایای Async/Await:
مثال‌های پایه Async/Await:
using System;
using System.Threading.Tasks;
using System.Net.Http;
using System.IO;

public class AsyncBasicExamples
{
    // متد async ساده
    public static async Task<string> GetMessageAsync()
    {
        Console.WriteLine("Starting async operation...");
        
        // شبیه‌سازی عملیات طولانی‌مدت
        await Task.Delay(2000); // 2 ثانیه انتظار
        
        Console.WriteLine("Async operation completed!");
        return "Hello from async method!";
    }
    
    // متد async با return value
    public static async Task<int> CalculateAsync(int number)
    {
        Console.WriteLine($"Starting calculation for {number}...");
        
        // شبیه‌سازی محاسبه پیچیده
        await Task.Delay(1000);
        
        int result = number * number;
        Console.WriteLine($"Calculation completed: {number}² = {result}");
        
        return result;
    }
    
    // متد async بدون return value
    public static async Task LogMessageAsync(string message)
    {
        Console.WriteLine($"Logging: {message}");
        
        // شبیه‌سازی نوشتن در فایل
        await Task.Delay(500);
        
        Console.WriteLine("Log written successfully");
    }
    
    // متد async با exception handling
    public static async Task<string> RiskyOperationAsync(bool shouldFail)
    {
        Console.WriteLine("Starting risky operation...");
        
        await Task.Delay(1000);
        
        if (shouldFail)
        {
            throw new InvalidOperationException("Operation failed as requested");
        }
        
        return "Risky operation succeeded!";
    }
    
    public static async Task DemonstrateBasicAsync()
    {
        Console.WriteLine("=== Basic Async/Await Examples ===");
        
        try
        {
            // فراخوانی متد async
            string message = await GetMessageAsync();
            Console.WriteLine($"Received: {message}");
            
            // فراخوانی چندین متد async به صورت متوالی
            int result1 = await CalculateAsync(5);
            int result2 = await CalculateAsync(7);
            Console.WriteLine($"Results: {result1}, {result2}");
            
            // فراخوانی متد async بدون return value
            await LogMessageAsync("This is a test message");
            
            // Exception handling در async
            try
            {
                string riskyResult = await RiskyOperationAsync(false);
                Console.WriteLine($"Success: {riskyResult}");
                
                // این یکی exception پرتاب می‌کند
                await RiskyOperationAsync(true);
            }
            catch (InvalidOperationException ex)
            {
                Console.WriteLine($"Caught exception: {ex.Message}");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Unexpected error: {ex.Message}");
        }
    }
}
مثال Parallel Async Operations:
public class ParallelAsyncExamples
{
    public static async Task<string> DownloadDataAsync(string url, int delayMs)
    {
        Console.WriteLine($"Starting download from {url}...");
        
        // شبیه‌سازی دانلود
        await Task.Delay(delayMs);
        
        Console.WriteLine($"Download from {url} completed!");
        return $"Data from {url} (took {delayMs}ms)";
    }
    
    public static async Task<int> ProcessDataAsync(string data, int processingTime)
    {
        Console.WriteLine($"Processing: {data}");
        
        await Task.Delay(processingTime);
        
        int result = data.Length;
        Console.WriteLine($"Processing completed. Result: {result}");
        
        return result;
    }
    
    public static async Task DemonstrateParallelAsync()
    {
        Console.WriteLine("\n=== Parallel Async Operations ===");
        
        // 1. اجرای متوالی (Sequential)
        Console.WriteLine("Sequential execution:");
        var startTime = DateTime.Now;
        
        string data1 = await DownloadDataAsync("https://api1.example.com", 1000);
        string data2 = await DownloadDataAsync("https://api2.example.com", 1500);
        string data3 = await DownloadDataAsync("https://api3.example.com", 800);
        
        var sequentialTime = DateTime.Now - startTime;
        Console.WriteLine($"Sequential time: {sequentialTime.TotalMilliseconds}ms");
        
        // 2. اجرای موازی (Parallel) با Task.WhenAll
        Console.WriteLine("\nParallel execution with Task.WhenAll:");
        startTime = DateTime.Now;
        
        Task<string> task1 = DownloadDataAsync("https://api1.example.com", 1000);
        Task<string> task2 = DownloadDataAsync("https://api2.example.com", 1500);
        Task<string> task3 = DownloadDataAsync("https://api3.example.com", 800);
        
        string[] results = await Task.WhenAll(task1, task2, task3);
        
        var parallelTime = DateTime.Now - startTime;
        Console.WriteLine($"Parallel time: {parallelTime.TotalMilliseconds}ms");
        
        Console.WriteLine("Results:");
        for (int i = 0; i < results.Length; i++)
        {
            Console.WriteLine($"  {i + 1}: {results[i]}");
        }
        
        // 3. اجرای موازی با پردازش
        Console.WriteLine("\nParallel download and processing:");
        startTime = DateTime.Now;
        
        var downloadTasks = new[]
        {
            DownloadDataAsync("https://service1.com", 800),
            DownloadDataAsync("https://service2.com", 1200),
            DownloadDataAsync("https://service3.com", 600)
        };
        
        var downloadResults = await Task.WhenAll(downloadTasks);
        
        var processingTasks = downloadResults.Select((data, index) => 
            ProcessDataAsync(data, (index + 1) * 300)).ToArray();
        
        var processingResults = await Task.WhenAll(processingTasks);
        
        var totalTime = DateTime.Now - startTime;
        Console.WriteLine($"Total time (download + processing): {totalTime.TotalMilliseconds}ms");
        Console.WriteLine($"Processing results: [{string.Join(", ", processingResults)}]");
    }
}
مثال Real-world HTTP Client:
using System.Text.Json;

public class HttpClientExample
{
    private static readonly HttpClient httpClient = new HttpClient();
    
    public class Post
    {
        public int UserId { get; set; }
        public int Id { get; set; }
        public string Title { get; set; }
        public string Body { get; set; }
    }
    
    public static async Task<Post> GetPostAsync(int postId)
    {
        try
        {
            Console.WriteLine($"Fetching post {postId}...");
            
            string url = $"https://jsonplaceholder.typicode.com/posts/{postId}";
            HttpResponseMessage response = await httpClient.GetAsync(url);
            
            response.EnsureSuccessStatusCode();
            
            string jsonContent = await response.Content.ReadAsStringAsync();
            Post post = JsonSerializer.Deserialize<Post>(jsonContent, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            });
            
            Console.WriteLine($"Post {postId} fetched successfully");
            return post;
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"HTTP error fetching post {postId}: {ex.Message}");
            throw;
        }
        catch (JsonException ex)
        {
            Console.WriteLine($"JSON parsing error for post {postId}: {ex.Message}");
            throw;
        }
    }
    
    public static async Task<List<Post>> GetMultiplePostsAsync(int[] postIds)
    {
        Console.WriteLine($"Fetching {postIds.Length} posts in parallel...");
        
        var tasks = postIds.Select(GetPostAsync).ToArray();
        
        try
        {
            Post[] posts = await Task.WhenAll(tasks);
            return posts.ToList();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error fetching multiple posts: {ex.Message}");
            
            // بررسی کدام taskها موفق بودند
            var completedTasks = tasks.Where(t => t.IsCompletedSuccessfully).ToArray();
            Console.WriteLine($"{completedTasks.Length} out of {tasks.Length} requests succeeded");
            
            throw;
        }
    }
    
    public static async Task DemonstrateHttpClient()
    {
        Console.WriteLine("\n=== HTTP Client Async Examples ===");
        
        try
        {
            // دریافت یک post
            Post singlePost = await GetPostAsync(1);
            Console.WriteLine($"Single Post: {singlePost.Title}");
            
            // دریافت چندین post به صورت موازی
            int[] postIds = { 1, 2, 3, 4, 5 };
            List<Post> multiplePosts = await GetMultiplePostsAsync(postIds);
            
            Console.WriteLine($"\nFetched {multiplePosts.Count} posts:");
            foreach (var post in multiplePosts)
            {
                Console.WriteLine($"  {post.Id}: {post.Title.Substring(0, Math.Min(50, post.Title.Length))}...");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Demo failed: {ex.Message}");
        }
    }
}
مثال File I/O Async:
public class FileAsyncExamples
{
    public static async Task WriteFileAsync(string filePath, string content)
    {
        Console.WriteLine($"Writing to file: {filePath}");
        
        try
        {
            await File.WriteAllTextAsync(filePath, content);
            Console.WriteLine("File write completed");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error writing file: {ex.Message}");
            throw;
        }
    }
    
    public static async Task<string> ReadFileAsync(string filePath)
    {
        Console.WriteLine($"Reading from file: {filePath}");
        
        try
        {
            string content = await File.ReadAllTextAsync(filePath);
            Console.WriteLine($"File read completed ({content.Length} characters)");
            return content;
        }
        catch (FileNotFoundException)
        {
            Console.WriteLine("File not found");
            return null;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error reading file: {ex.Message}");
            throw;
        }
    }
    
    public static async Task ProcessMultipleFilesAsync(string[] filePaths, string[] contents)
    {
        Console.WriteLine($"Processing {filePaths.Length} files...");
        
        // نوشتن فایل‌ها به صورت موازی
        var writeTasks = filePaths.Zip(contents, (path, content) => 
            WriteFileAsync(path, content)).ToArray();
        
        await Task.WhenAll(writeTasks);
        Console.WriteLine("All files written");
        
        // خواندن فایل‌ها به صورت موازی
        var readTasks = filePaths.Select(ReadFileAsync).ToArray();
        string[] readContents = await Task.WhenAll(readTasks);
        
        Console.WriteLine("All files read:");
        for (int i = 0; i < filePaths.Length; i++)
        {
            Console.WriteLine($"  {filePaths[i]}: {readContents[i]?.Length ?? 0} characters");
        }
    }
    
    public static async Task DemonstrateFileAsync()
    {
        Console.WriteLine("\n=== File I/O Async Examples ===");
        
        string[] filePaths = {
            "temp1.txt",
            "temp2.txt", 
            "temp3.txt"
        };
        
        string[] contents = {
            "This is content for file 1\nWith multiple lines",
            "Content for file 2\nAnother line here",
            "File 3 content\nYet another line"
        };
        
        try
        {
            await ProcessMultipleFilesAsync(filePaths, contents);
            
            // پاک کردن فایل‌های موقت
            foreach (string filePath in filePaths)
            {
                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }
            }
            Console.WriteLine("Temporary files cleaned up");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"File processing failed: {ex.Message}");
        }
    }
}
بهترین شیوه‌های Async/Await:

۶۹. Task Parallel Library (TPL) در C# چیست؟

پاسخ:

Task Parallel Library (TPL) مجموعه‌ای از APIها در .NET است که برنامه‌نویسی موازی (Parallel Programming) را ساده‌تر می‌کند. TPL در فضای نام System.Threading.Tasks قرار دارد و شامل کلاس‌های Task، Task<T>، Parallel و PLINQ می‌شود. این کتابخانه به شما اجازه می‌دهد تا از قدرت پردازنده‌های چند هسته‌ای بهره‌برداری کنید و عملیات‌های محاسباتی سنگین را سریع‌تر انجام دهید.

اجزای اصلی TPL:
مثال‌های Task و Task<T>:
using System;
using System.Threading;
using System.Threading.Tasks;

public class TaskExamples
{
    public static void LongRunningOperation(string name, int durationMs)
    {
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] {name} started");
        Thread.Sleep(durationMs);
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] {name} completed");
    }
    
    public static int CalculateSum(int start, int end)
    {
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] Calculating sum from {start} to {end}");
        
        int sum = 0;
        for (int i = start; i <= end; i++)
        {
            sum += i;
            // شبیه‌سازی محاسبه سنگین
            if (i % 100000 == 0)
                Thread.Sleep(1);
        }
        
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] Sum calculation completed: {sum}");
        return sum;
    }
    
    public static async Task DemonstrateBasicTasks()
    {
        Console.WriteLine("=== Basic Task Examples ===");
        
        // 1. Task بدون return value
        Console.WriteLine("Creating tasks without return value:");
        
        Task task1 = Task.Run(() => LongRunningOperation("Task 1", 1000));
        Task task2 = Task.Run(() => LongRunningOperation("Task 2", 1500));
        Task task3 = Task.Run(() => LongRunningOperation("Task 3", 800));
        
        // انتظار برای تمام taskها
        await Task.WhenAll(task1, task2, task3);
        Console.WriteLine("All tasks completed");
        
        // 2. Task با return value
        Console.WriteLine("\nCreating tasks with return value:");
        
        Task<int> sumTask1 = Task.Run(() => CalculateSum(1, 100000));
        Task<int> sumTask2 = Task.Run(() => CalculateSum(100001, 200000));
        Task<int> sumTask3 = Task.Run(() => CalculateSum(200001, 300000));
        
        int[] results = await Task.WhenAll(sumTask1, sumTask2, sumTask3);
        int totalSum = results.Sum();
        
        Console.WriteLine($"Individual results: [{string.Join(", ", results)}]");
        Console.WriteLine($"Total sum: {totalSum}");
        
        // 3. Task.Factory.StartNew (پیشرفته‌تر)
        Console.WriteLine("\nUsing Task.Factory.StartNew:");
        
        Task<string> factoryTask = Task.Factory.StartNew(() =>
        {
            Thread.Sleep(1000);
            return $"Factory task completed on thread {Thread.CurrentThread.ManagedThreadId}";
        }, TaskCreationOptions.LongRunning);
        
        string factoryResult = await factoryTask;
        Console.WriteLine(factoryResult);
    }
}
مثال Parallel Class:
public class ParallelExamples
{
    public static void ProcessItem(int item)
    {
        // شبیه‌سازی پردازش سنگین
        double result = Math.Sqrt(item) * Math.Sin(item);
        Thread.Sleep(10); // شبیه‌سازی تأخیر
        
        if (item % 1000 == 0)
            Console.WriteLine($"Processed item {item} on thread {Thread.CurrentThread.ManagedThreadId}");
    }
    
    public static int ProcessAndSum(int item)
    {
        // پردازش و بازگشت نتیجه
        Thread.Sleep(1);
        return item * item;
    }
    
    public static void DemonstrateParallelClass()
    {
        Console.WriteLine("\n=== Parallel Class Examples ===");
        
        // 1. Parallel.For
        Console.WriteLine("Parallel.For example:");
        var stopwatch = System.Diagnostics.Stopwatch.StartNew();
        
        Parallel.For(0, 10000, ProcessItem);
        
        stopwatch.Stop();
        Console.WriteLine($"Parallel.For completed in {stopwatch.ElapsedMilliseconds}ms");
        
        // مقایسه با حلقه معمولی
        Console.WriteLine("\nSequential for comparison:");
        stopwatch.Restart();
        
        for (int i = 0; i < 10000; i++)
        {
            ProcessItem(i);
        }
        
        stopwatch.Stop();
        Console.WriteLine($"Sequential for completed in {stopwatch.ElapsedMilliseconds}ms");
        
        // 2. Parallel.ForEach
        Console.WriteLine("\nParallel.ForEach example:");
        var numbers = Enumerable.Range(1, 1000).ToArray();
        var results = new int[numbers.Length];
        
        stopwatch.Restart();
        
        Parallel.ForEach(numbers, (number, loop, index) =>
        {
            results[index] = ProcessAndSum(number);
        });
        
        stopwatch.Stop();
        Console.WriteLine($"Parallel.ForEach completed in {stopwatch.ElapsedMilliseconds}ms");
        Console.WriteLine($"Sum of squares: {results.Sum()}");
        
        // 3. Parallel.Invoke
        Console.WriteLine("\nParallel.Invoke example:");
        stopwatch.Restart();
        
        Parallel.Invoke(
            () => {
                Console.WriteLine($"Action 1 started on thread {Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(1000);
                Console.WriteLine("Action 1 completed");
            },
            () => {
                Console.WriteLine($"Action 2 started on thread {Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(1500);
                Console.WriteLine("Action 2 completed");
            },
            () => {
                Console.WriteLine($"Action 3 started on thread {Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(800);
                Console.WriteLine("Action 3 completed");
            }
        );
        
        stopwatch.Stop();
        Console.WriteLine($"Parallel.Invoke completed in {stopwatch.ElapsedMilliseconds}ms");
    }
}
مثال PLINQ (Parallel LINQ):
public class PLINQExamples
{
    public static bool IsPrime(int number)
    {
        if (number < 2) return false;
        if (number == 2) return true;
        if (number % 2 == 0) return false;
        
        for (int i = 3; i * i <= number; i += 2)
        {
            if (number % i == 0)
                return false;
        }
        return true;
    }
    
    public static double ComplexCalculation(int input)
    {
        // شبیه‌سازی محاسبه پیچیده
        double result = input;
        for (int i = 0; i < 1000; i++)
        {
            result = Math.Sqrt(result + i) * Math.Sin(result);
        }
        return result;
    }
    
    public static void DemonstratePLINQ()
    {
        Console.WriteLine("\n=== PLINQ Examples ===");
        
        var numbers = Enumerable.Range(1, 100000).ToArray();
        
        // 1. Sequential LINQ
        Console.WriteLine("Sequential LINQ:");
        var stopwatch = System.Diagnostics.Stopwatch.StartNew();
        
        var sequentialPrimes = numbers
            .Where(IsPrime)
            .Take(100)
            .ToArray();
        
        stopwatch.Stop();
        Console.WriteLine($"Sequential: Found {sequentialPrimes.Length} primes in {stopwatch.ElapsedMilliseconds}ms");
        
        // 2. Parallel LINQ
        Console.WriteLine("\nParallel LINQ:");
        stopwatch.Restart();
        
        var parallelPrimes = numbers
            .AsParallel()
            .Where(IsPrime)
            .Take(100)
            .ToArray();
        
        stopwatch.Stop();
        Console.WriteLine($"Parallel: Found {parallelPrimes.Length} primes in {stopwatch.ElapsedMilliseconds}ms");
        
        // 3. PLINQ با پیکربندی
        Console.WriteLine("\nPLINQ with configuration:");
        stopwatch.Restart();
        
        var configuredResults = numbers
            .AsParallel()
            .WithDegreeOfParallelism(Environment.ProcessorCount) // تعداد thread ها
            .WithExecutionMode(ParallelExecutionMode.ForceParallelism) // اجبار به موازی سازی
            .Where(n => n % 2 == 0) // فقط اعداد زوج
            .Select(ComplexCalculation) // محاسبه پیچیده
            .Where(result => result > 0) // فیلتر نتایج
            .Take(1000)
            .ToArray();
        
        stopwatch.Stop();
        Console.WriteLine($"Configured PLINQ: Processed {configuredResults.Length} items in {stopwatch.ElapsedMilliseconds}ms");
        
        // 4. PLINQ Aggregation
        Console.WriteLine("\nPLINQ Aggregation:");
        stopwatch.Restart();
        
        var stats = numbers
            .AsParallel()
            .Where(n => n <= 10000)
            .Select(n => (double)n)
            .Aggregate(
                new { Sum = 0.0, Count = 0, Min = double.MaxValue, Max = double.MinValue },
                (acc, value) => new
                {
                    Sum = acc.Sum + value,
                    Count = acc.Count + 1,
                    Min = Math.Min(acc.Min, value),
                    Max = Math.Max(acc.Max, value)
                },
                (acc1, acc2) => new
                {
                    Sum = acc1.Sum + acc2.Sum,
                    Count = acc1.Count + acc2.Count,
                    Min = Math.Min(acc1.Min, acc2.Min),
                    Max = Math.Max(acc1.Max, acc2.Max)
                }
            );
        
        stopwatch.Stop();
        Console.WriteLine($"PLINQ Aggregation completed in {stopwatch.ElapsedMilliseconds}ms");
        Console.WriteLine($"Count: {stats.Count}, Sum: {stats.Sum}, Min: {stats.Min}, Max: {stats.Max}");
        Console.WriteLine($"Average: {stats.Sum / stats.Count:F2}");
    }
}
مثال Cancellation و Exception Handling:
public class CancellationExamples
{
    public static async Task LongRunningTaskWithCancellation(string name, int durationMs, CancellationToken cancellationToken)
    {
        Console.WriteLine($"{name} started");
        
        try
        {
            for (int i = 0; i < durationMs / 100; i++)
            {
                cancellationToken.ThrowIfCancellationRequested();
                await Task.Delay(100, cancellationToken);
                
                if (i % 10 == 0)
                    Console.WriteLine($"{name} progress: {i * 100}ms");
            }
            
            Console.WriteLine($"{name} completed successfully");
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine($"{name} was cancelled");
            throw;
        }
    }
    
    public static async Task DemonstrateCancellation()
    {
        Console.WriteLine("\n=== Cancellation Examples ===");
        
        // 1. Cancellation با timeout
        Console.WriteLine("Task with timeout:");
        using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3)))
        {
            try
            {
                await LongRunningTaskWithCancellation("Task with timeout", 5000, cts.Token);
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("Task was cancelled due to timeout");
            }
        }
        
        // 2. Manual cancellation
        Console.WriteLine("\nManual cancellation:");
        using (var cts = new CancellationTokenSource())
        {
            var task1 = LongRunningTaskWithCancellation("Manual task 1", 3000, cts.Token);
            var task2 = LongRunningTaskWithCancellation("Manual task 2", 4000, cts.Token);
            
            // لغو پس از 1.5 ثانیه
            _ = Task.Delay(1500).ContinueWith(_ => {
                Console.WriteLine("Requesting cancellation...");
                cts.Cancel();
            });
            
            try
            {
                await Task.WhenAll(task1, task2);
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("One or more tasks were cancelled");
            }
        }
        
        // 3. Exception handling در parallel operations
        Console.WriteLine("\nException handling in parallel operations:");
        
        var faultyTasks = new[]
        {
            Task.Run(() => {
                Thread.Sleep(1000);
                if (DateTime.Now.Millisecond % 2 == 0)
                    throw new InvalidOperationException("Random error in task 1");
                return "Task 1 success";
            }),
            Task.Run(() => {
                Thread.Sleep(1500);
                return "Task 2 success";
            }),
            Task.Run(() => {
                Thread.Sleep(800);
                throw new ArgumentException("Error in task 3");
            })
        };
        
        try
        {
            string[] results = await Task.WhenAll(faultyTasks);
            Console.WriteLine($"All tasks succeeded: {string.Join(", ", results)}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"At least one task failed: {ex.Message}");
            
            // بررسی وضعیت هر task
            for (int i = 0; i < faultyTasks.Length; i++)
            {
                var task = faultyTasks[i];
                Console.WriteLine($"Task {i + 1}: {task.Status}");
                
                if (task.IsFaulted && task.Exception != null)
                {
                    Console.WriteLine($"  Exception: {task.Exception.InnerException?.Message}");
                }
                else if (task.IsCompletedSuccessfully)
                {
                    Console.WriteLine($"  Result: {task.Result}");
                }
            }
        }
    }
}
بهترین شیوه‌های TPL:

۷۰. Memory Management و Garbage Collection در C# چیست؟

پاسخ:

Memory Management (مدیریت حافظه) در C# به صورت خودکار توسط .NET Runtime انجام می‌شود. Garbage Collector (GC) مسئول آزادسازی حافظه اشیاء غیرقابل دسترس است و برنامه‌نویسان معمولاً نیازی به مدیریت دستی حافظه ندارند. GC از الگوریتم‌های پیشرفته‌ای برای بهینه‌سازی عملکرد و کاهش تأثیر بر برنامه استفاده می‌کند.

اجزای اصلی Memory Management:
مثال Memory Allocation و GC:
using System;
using System.Runtime;

public class MemoryExample
{
    public class LargeObject
    {
        private byte[] data;
        public string Name { get; set; }
        
        public LargeObject(string name, int sizeInMB)
        {
            Name = name;
            data = new byte[sizeInMB * 1024 * 1024]; // تخصیص حافظه بزرگ
            Console.WriteLine($"Created {name} with {sizeInMB}MB");
        }
        
        ~LargeObject()
        {
            Console.WriteLine($"Finalizing {Name}");
        }
    }
    
    public class SmallObject
    {
        public int Id { get; set; }
        public string Data { get; set; }
        
        public SmallObject(int id)
        {
            Id = id;
            Data = $"Data for object {id}";
        }
        
        ~SmallObject()
        {
            Console.WriteLine($"Finalizing SmallObject {Id}");
        }
    }
    
    public static void DemonstrateMemoryAllocation()
    {
        Console.WriteLine("=== Memory Allocation Examples ===");
        
        // نمایش وضعیت اولیه حافظه
        PrintMemoryInfo("Initial state");
        
        // تخصیص اشیاء کوچک
        Console.WriteLine("\nAllocating small objects:");
        var smallObjects = new SmallObject[1000];
        for (int i = 0; i < 1000; i++)
        {
            smallObjects[i] = new SmallObject(i);
        }
        
        PrintMemoryInfo("After small objects allocation");
        
        // تخصیص اشیاء بزرگ
        Console.WriteLine("\nAllocating large objects:");
        var largeObjects = new LargeObject[3];
        for (int i = 0; i < 3; i++)
        {
            largeObjects[i] = new LargeObject($"LargeObj{i}", 10); // 10MB هر کدام
        }
        
        PrintMemoryInfo("After large objects allocation");
        
        // آزاد کردن مراجع
        Console.WriteLine("\nReleasing references:");
        smallObjects = null;
        largeObjects = null;
        
        PrintMemoryInfo("After releasing references");
        
        // اجرای دستی GC
        Console.WriteLine("\nForcing garbage collection:");
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        
        PrintMemoryInfo("After forced GC");
    }
    
    public static void PrintMemoryInfo(string stage)
    {
        Console.WriteLine($"\n--- {stage} ---");
        Console.WriteLine($"Total Memory: {GC.GetTotalMemory(false) / 1024 / 1024:F2} MB");
        Console.WriteLine($"Gen 0 Collections: {GC.CollectionCount(0)}");
        Console.WriteLine($"Gen 1 Collections: {GC.CollectionCount(1)}");
        Console.WriteLine($"Gen 2 Collections: {GC.CollectionCount(2)}");
        
        // اطلاعات تفصیلی GC (در .NET 6+)
        var gcInfo = GC.GetGCMemoryInfo();
        Console.WriteLine($"Heap Size: {gcInfo.HeapSizeBytes / 1024 / 1024:F2} MB");
        Console.WriteLine($"Memory Load: {gcInfo.MemoryLoadBytes / 1024 / 1024:F2} MB");
    }
}
مثال IDisposable Pattern:
using System;
using System.IO;

// پیاده‌سازی صحیح IDisposable Pattern
public class ResourceManager : IDisposable
{
    private FileStream _fileStream;
    private StreamWriter _writer;
    private bool _disposed = false;
    
    public ResourceManager(string filePath)
    {
        _fileStream = new FileStream(filePath, FileMode.Create);
        _writer = new StreamWriter(_fileStream);
        Console.WriteLine($"ResourceManager created for {filePath}");
    }
    
    public void WriteData(string data)
    {
        if (_disposed)
            throw new ObjectDisposedException(nameof(ResourceManager));
            
        _writer.WriteLine($"[{DateTime.Now:HH:mm:ss}] {data}");
        _writer.Flush();
    }
    
    // Public Dispose method
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this); // جلوگیری از فراخوانی finalizer
    }
    
    // Protected virtual Dispose method
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // آزادسازی managed resources
                _writer?.Dispose();
                _fileStream?.Dispose();
                Console.WriteLine("Managed resources disposed");
            }
            
            // آزادسازی unmanaged resources (اگر وجود داشته باشد)
            // در این مثال unmanaged resource نداریم
            
            _disposed = true;
            Console.WriteLine("ResourceManager disposed");
        }
    }
    
    // Finalizer (destructor)
    ~ResourceManager()
    {
        Console.WriteLine("ResourceManager finalizer called");
        Dispose(false);
    }
}

// کلاس برای نمایش weak references
public class WeakReferenceExample
{
    public class DataHolder
    {
        public byte[] Data { get; set; }
        public string Name { get; set; }
        
        public DataHolder(string name, int sizeKB)
        {
            Name = name;
            Data = new byte[sizeKB * 1024];
            Console.WriteLine($"DataHolder '{name}' created with {sizeKB}KB");
        }
        
        ~DataHolder()
        {
            Console.WriteLine($"DataHolder '{Name}' finalized");
        }
    }
    
    public static void DemonstrateWeakReferences()
    {
        Console.WriteLine("\n=== Weak References Example ===");
        
        DataHolder strongRef = new DataHolder("StrongRef", 100);
        WeakReference weakRef = new WeakReference(new DataHolder("WeakRef", 100));
        
        Console.WriteLine($"Strong ref is alive: {strongRef != null}");
        Console.WriteLine($"Weak ref is alive: {weakRef.IsAlive}");
        Console.WriteLine($"Weak ref target: {((DataHolder)weakRef.Target)?.Name}");
        
        // اجرای GC
        Console.WriteLine("\nForcing GC...");
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        
        Console.WriteLine($"Strong ref is alive: {strongRef != null}");
        Console.WriteLine($"Weak ref is alive: {weakRef.IsAlive}");
        
        if (weakRef.IsAlive)
        {
            Console.WriteLine($"Weak ref target: {((DataHolder)weakRef.Target)?.Name}");
        }
        else
        {
            Console.WriteLine("Weak ref target has been collected");
        }
        
        strongRef = null;
        
        Console.WriteLine("\nAfter releasing strong reference:");
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        
        Console.WriteLine($"Strong ref is alive: {strongRef != null}");
        Console.WriteLine($"Weak ref is alive: {weakRef.IsAlive}");
    }
}

public static void DemonstrateResourceManagement()
{
    Console.WriteLine("\n=== Resource Management Examples ===");
    
    // 1. استفاده از using statement
    Console.WriteLine("Using statement example:");
    using (var resourceManager = new ResourceManager("test1.txt"))
    {
        resourceManager.WriteData("This is test data 1");
        resourceManager.WriteData("This is test data 2");
        // resourceManager.Dispose() به صورت خودکار فراخوانی می‌شود
    }
    
    // 2. استفاده از using declaration (C# 8+)
    Console.WriteLine("\nUsing declaration example:");
    {
        using var resourceManager2 = new ResourceManager("test2.txt");
        resourceManager2.WriteData("Using declaration data 1");
        resourceManager2.WriteData("Using declaration data 2");
        // resourceManager2.Dispose() در پایان scope فراخوانی می‌شود
    }
    
    // 3. مدیریت دستی (نه توصیه شده)
    Console.WriteLine("\nManual disposal example:");
    var resourceManager3 = new ResourceManager("test3.txt");
    try
    {
        resourceManager3.WriteData("Manual disposal data");
    }
    finally
    {
        resourceManager3.Dispose();
    }
    
    // 4. نمایش finalizer
    Console.WriteLine("\nFinalizer example (not disposing manually):");
    var resourceManager4 = new ResourceManager("test4.txt");
    resourceManager4.WriteData("Finalizer test data");
    resourceManager4 = null; // فقط مرجع را null می‌کنیم، Dispose فراخوانی نمی‌شود
    
    Console.WriteLine("Forcing GC to demonstrate finalizer:");
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
    
    // پاک کردن فایل‌های موقت
    string[] tempFiles = { "test1.txt", "test2.txt", "test3.txt", "test4.txt" };
    foreach (string file in tempFiles)
    {
        if (File.Exists(file))
        {
            File.Delete(file);
        }
    }
}
مثال Memory Profiling:
public class MemoryProfilingExample
{
    public class MemoryIntensiveClass
    {
        private static int _instanceCount = 0;
        private byte[] _data;
        public int Id { get; }
        
        public MemoryIntensiveClass(int sizeKB)
        {
            Id = ++_instanceCount;
            _data = new byte[sizeKB * 1024];
        }
        
        public void DoWork()
        {
            // شبیه‌سازی کار با داده‌ها
            for (int i = 0; i < _data.Length; i += 1024)
            {
                _data[i] = (byte)(i % 256);
            }
        }
        
        ~MemoryIntensiveClass()
        {
            Console.WriteLine($"MemoryIntensiveClass {Id} finalized");
        }
    }
    
    public static void DemonstrateMemoryProfiling()
    {
        Console.WriteLine("\n=== Memory Profiling Example ===");
        
        const int objectCount = 1000;
        const int objectSizeKB = 50;
        
        Console.WriteLine($"Creating {objectCount} objects of {objectSizeKB}KB each");
        
        var startTime = DateTime.Now;
        var startMemory = GC.GetTotalMemory(true); // true = force GC before measurement
        
        var objects = new MemoryIntensiveClass[objectCount];
        
        // تخصیص اشیاء
        for (int i = 0; i < objectCount; i++)
        {
            objects[i] = new MemoryIntensiveClass(objectSizeKB);
            objects[i].DoWork();
            
            if (i % 100 == 0)
            {
                var currentMemory = GC.GetTotalMemory(false);
                Console.WriteLine($"Created {i + 1} objects. Memory: {currentMemory / 1024 / 1024:F2} MB");
            }
        }
        
        var afterAllocationTime = DateTime.Now;
        var afterAllocationMemory = GC.GetTotalMemory(false);
        
        Console.WriteLine($"\nAllocation completed:");
        Console.WriteLine($"Time: {(afterAllocationTime - startTime).TotalMilliseconds:F0}ms");
        Console.WriteLine($"Memory increase: {(afterAllocationMemory - startMemory) / 1024 / 1024:F2} MB");
        Console.WriteLine($"Expected memory: {objectCount * objectSizeKB / 1024:F2} MB");
        
        // آزادسازی نیمی از اشیاء
        Console.WriteLine("\nReleasing half of the objects:");
        for (int i = 0; i < objectCount / 2; i++)
        {
            objects[i] = null;
        }
        
        var beforeGCMemory = GC.GetTotalMemory(false);
        Console.WriteLine($"Memory before GC: {beforeGCMemory / 1024 / 1024:F2} MB");
        
        // اجرای GC
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        
        var afterGCMemory = GC.GetTotalMemory(false);
        Console.WriteLine($"Memory after GC: {afterGCMemory / 1024 / 1024:F2} MB");
        Console.WriteLine($"Memory freed: {(beforeGCMemory - afterGCMemory) / 1024 / 1024:F2} MB");
        
        // آزادسازی بقیه اشیاء
        objects = null;
        
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        
        var finalMemory = GC.GetTotalMemory(false);
        Console.WriteLine($"Final memory: {finalMemory / 1024 / 1024:F2} MB");
        Console.WriteLine($"Total memory freed: {(afterAllocationMemory - finalMemory) / 1024 / 1024:F2} MB");
        
        // نمایش آمار GC
        Console.WriteLine("\nGC Statistics:");
        Console.WriteLine($"Gen 0 collections: {GC.CollectionCount(0)}");
        Console.WriteLine($"Gen 1 collections: {GC.CollectionCount(1)}");
        Console.WriteLine($"Gen 2 collections: {GC.CollectionCount(2)}");
    }
}
بهترین شیوه‌های Memory Management:

۷۱. Pattern Matching در C# چیست؟

پاسخ:

Pattern Matching (تطبیق الگو) قابلیتی در C# است که به شما اجازه می‌دهد تا بررسی کنید که آیا یک مقدار دارای شکل خاصی است و در صورت تطبیق، اطلاعات مفیدی از آن مقدار استخراج کنید. این قابلیت در C# 7.0 معرفی شد و در نسخه‌های بعدی گسترش یافته است.

انواع Pattern Matching:
مثال‌های Pattern Matching:
using System;

public class PatternMatchingExamples
{
    public class Shape { }
    public class Circle : Shape 
    { 
        public double Radius { get; set; }
        public Circle(double radius) => 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 class Triangle : Shape 
    { 
        public double Base { get; set; }
        public double Height { get; set; }
        public Triangle(double @base, double height)
        {
            Base = @base;
            Height = height;
        }
    }

    // Type Pattern و Switch Expression
    public static double CalculateArea(Shape shape) => shape switch
    {
        Circle c => Math.PI * c.Radius * c.Radius,
        Rectangle r => r.Width * r.Height,
        Triangle t => 0.5 * t.Base * t.Height,
        null => 0,
        _ => throw new ArgumentException("Unknown shape type")
    };

    // Property Pattern
    public static string DescribeShape(Shape shape) => shape switch
    {
        Circle { Radius: > 10 } => "Large circle",
        Circle { Radius: <= 5 } => "Small circle", 
        Circle => "Medium circle",
        Rectangle { Width: var w, Height: var h } when w == h => "Square",
        Rectangle { Width: > 10, Height: > 10 } => "Large rectangle",
        Rectangle => "Rectangle",
        Triangle { Base: > 0, Height: > 0 } => "Valid triangle",
        null => "No shape",
        _ => "Unknown shape"
    };

    // Tuple Pattern
    public static string GetQuadrant(int x, int y) => (x, y) switch
    {
        (0, 0) => "Origin",
        (var a, var b) when a > 0 && b > 0 => "First quadrant",
        (var a, var b) when a < 0 && b > 0 => "Second quadrant", 
        (var a, var b) when a < 0 && b < 0 => "Third quadrant",
        (var a, var b) when a > 0 && b < 0 => "Fourth quadrant",
        (_, 0) => "On X-axis",
        (0, _) => "On Y-axis"
    };

    // Relational Pattern (C# 9+)
    public static string CategorizeTemperature(double temp) => temp switch
    {
        < 0 => "Freezing",
        >= 0 and < 10 => "Cold",
        >= 10 and < 25 => "Moderate", 
        >= 25 and < 35 => "Warm",
        >= 35 => "Hot"
    };

    public static void DemonstratePatternMatching()
    {
        Console.WriteLine("=== Pattern Matching Examples ===");

        // Test shapes
        Shape[] shapes = {
            new Circle(3),
            new Circle(12),
            new Rectangle(5, 5),
            new Rectangle(8, 12),
            new Triangle(6, 4),
            null
        };

        foreach (var shape in shapes)
        {
            if (shape != null)
            {
                double area = CalculateArea(shape);
                string description = DescribeShape(shape);
                Console.WriteLine($"{shape.GetType().Name}: Area = {area:F2}, Description = {description}");
            }
            else
            {
                Console.WriteLine($"Null shape: Area = {CalculateArea(shape)}, Description = {DescribeShape(shape)}");
            }
        }

        // Test quadrants
        Console.WriteLine("\n--- Quadrant Examples ---");
        (int, int)[] points = { (0, 0), (5, 3), (-2, 4), (-3, -1), (2, -5), (0, 7), (4, 0) };
        
        foreach (var (x, y) in points)
        {
            Console.WriteLine($"Point ({x}, {y}): {GetQuadrant(x, y)}");
        }

        // Test temperature categories
        Console.WriteLine("\n--- Temperature Categories ---");
        double[] temperatures = { -5, 2, 15, 28, 40 };
        
        foreach (var temp in temperatures)
        {
            Console.WriteLine($"{temp}°C: {CategorizeTemperature(temp)}");
        }
    }
}

۷۲. Records در C# چیست؟

پاسخ:

Records نوع جدیدی از کلاس در C# 9.0 هستند که برای ذخیره‌سازی داده طراحی شده‌اند. Records به صورت پیش‌فرض immutable هستند و قابلیت‌های مفیدی مانند value equality، with expressions و deconstruction ارائه می‌دهند. آن‌ها برای Data Transfer Objects (DTOs) و Value Objects ایده‌آل هستند.

ویژگی‌های Records:
مثال‌های Records:
using System;

// Record با positional syntax
public record Person(string FirstName, string LastName, int Age);

// Record با property syntax
public record Employee
{
    public string Name { get; init; }
    public string Department { get; init; }
    public decimal Salary { get; init; }
    public DateTime HireDate { get; init; }
}

// Record با validation
public record Product(string Name, decimal Price, string Category)
{
    public Product(string Name, decimal Price, string Category) : this(Name, Price, Category)
    {
        if (string.IsNullOrWhiteSpace(Name))
            throw new ArgumentException("Name cannot be empty");
        if (Price < 0)
            throw new ArgumentException("Price cannot be negative");
    }
}

// Record inheritance
public record Vehicle(string Make, string Model, int Year);
public record Car(string Make, string Model, int Year, int Doors) : Vehicle(Make, Model, Year);
public record Truck(string Make, string Model, int Year, double PayloadCapacity) : Vehicle(Make, Model, Year);

public class RecordExamples
{
    public static void DemonstrateRecords()
    {
        Console.WriteLine("=== Records Examples ===");

        // Creating records
        var person1 = new Person("احمد", "محمدی", 30);
        var person2 = new Person("فاطمه", "احمدی", 25);
        
        Console.WriteLine($"Person 1: {person1}");
        Console.WriteLine($"Person 2: {person2}");

        // Value equality
        var person3 = new Person("احمد", "محمدی", 30);
        Console.WriteLine($"person1 == person3: {person1 == person3}"); // True
        Console.WriteLine($"person1.Equals(person3): {person1.Equals(person3)}"); // True
        Console.WriteLine($"ReferenceEquals(person1, person3): {ReferenceEquals(person1, person3)}"); // False

        // With expressions
        var olderPerson = person1 with { Age = 31 };
        Console.WriteLine($"Original: {person1}");
        Console.WriteLine($"Modified: {olderPerson}");

        // Deconstruction
        var (firstName, lastName, age) = person1;
        Console.WriteLine($"Deconstructed: {firstName} {lastName}, Age: {age}");

        // Employee record
        var employee = new Employee
        {
            Name = "علی رضایی",
            Department = "IT",
            Salary = 5000m,
            HireDate = new DateTime(2020, 1, 15)
        };

        Console.WriteLine($"Employee: {employee}");

        var promotedEmployee = employee with { Salary = 6000m, Department = "Senior IT" };
        Console.WriteLine($"Promoted: {promotedEmployee}");

        // Vehicle inheritance
        var car = new Car("Toyota", "Camry", 2023, 4);
        var truck = new Truck("Ford", "F-150", 2023, 1.5);

        Console.WriteLine($"Car: {car}");
        Console.WriteLine($"Truck: {truck}");

        // Pattern matching with records
        Console.WriteLine("\n--- Pattern Matching with Records ---");
        Vehicle[] vehicles = { car, truck };

        foreach (var vehicle in vehicles)
        {
            var description = vehicle switch
            {
                Car { Doors: 2 } => "Two-door car",
                Car { Doors: 4 } => "Four-door car", 
                Car c => $"Car with {c.Doors} doors",
                Truck { PayloadCapacity: > 2.0 } => "Heavy-duty truck",
                Truck t => $"Light truck (payload: {t.PayloadCapacity} tons)",
                _ => "Unknown vehicle"
            };
            
            Console.WriteLine($"{vehicle.Make} {vehicle.Model}: {description}");
        }
    }
}

۷۳. Global Using Statements در C# چیست؟

پاسخ:

Global Using Statements قابلیتی در C# 10 است که به شما اجازه می‌دهد تا دستورات using را یک بار تعریف کنید و در تمام فایل‌های پروژه استفاده کنید. این کار به کاهش تکرار کد و بهبود خوانایی کمک می‌کند. همچنین Implicit Usings نیز در .NET 6 معرفی شد که using های رایج را به صورت خودکار اضافه می‌کند.

مزایای Global Usings:
مثال Global Usings:
// GlobalUsings.cs
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Text;
global using System.Threading.Tasks;
global using System.Text.Json;
global using System.IO;

// اضافه کردن using های سفارشی پروژه
global using MyProject.Models;
global using MyProject.Services;
global using MyProject.Utilities;

// Program.cs - بدون نیاز به using statements
public class Program
{
    public static async Task Main(string[] args)
    {
        // استفاده از System.Console بدون using System
        Console.WriteLine("Hello Global Usings!");
        
        // استفاده از List بدون using System.Collections.Generic
        var numbers = new List<int> { 1, 2, 3, 4, 5 };
        
        // استفاده از LINQ بدون using System.Linq
        var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();
        Console.WriteLine($"Even numbers: [{string.Join(", ", evenNumbers)}]");
        
        // استفاده از Task بدون using System.Threading.Tasks
        await Task.Delay(1000);
        Console.WriteLine("Delay completed!");
        
        // استفاده از JSON serialization بدون using System.Text.Json
        var person = new { Name = "احمد محمدی", Age = 30 };
        string json = JsonSerializer.Serialize(person);
        Console.WriteLine($"JSON: {json}");
        
        // استفاده از File I/O بدون using System.IO
        await File.WriteAllTextAsync("temp.txt", "Hello Global Usings!");
        string content = await File.ReadAllTextAsync("temp.txt");
        Console.WriteLine($"File content: {content}");
        
        // پاک کردن فایل موقت
        if (File.Exists("temp.txt"))
            File.Delete("temp.txt");
    }
}

۷۴. File-scoped Namespaces در C# چیست؟

پاسخ:

File-scoped Namespaces قابلیتی در C# 10 است که به شما اجازه می‌دهد تا namespace را برای کل فایل تعریف کنید بدون نیاز به استفاده از براکت‌های اضافی. این کار به کاهش سطح indentation و بهبود خوانایی کد کمک می‌کند، به خصوص در فایل‌هایی که فقط یک namespace دارند.

مزایای File-scoped Namespaces:
مقایسه Traditional و File-scoped:
// Traditional namespace (C# 1.0+)
using System;
using System.Collections.Generic;

namespace MyProject.Services
{
    public class UserService
    {
        private readonly List<User> _users;
        
        public UserService()
        {
            _users = new List<User>();
        }
        
        public void AddUser(User user)
        {
            if (user == null)
                throw new ArgumentNullException(nameof(user));
                
            _users.Add(user);
            Console.WriteLine($"User {user.Name} added successfully");
        }
        
        public User GetUser(int id)
        {
            return _users.FirstOrDefault(u => u.Id == id);
        }
        
        public List<User> GetAllUsers()
        {
            return _users.ToList();
        }
    }
    
    public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        
        public User(int id, string name, string email)
        {
            Id = id;
            Name = name;
            Email = email;
        }
        
        public override string ToString()
        {
            return $"User(Id: {Id}, Name: {Name}, Email: {Email})";
        }
    }
}

// File-scoped namespace (C# 10+)
using System;
using System.Collections.Generic;

namespace MyProject.Services;

public class UserService
{
    private readonly List<User> _users;
    
    public UserService()
    {
        _users = new List<User>();
    }
    
    public void AddUser(User user)
    {
        if (user == null)
            throw new ArgumentNullException(nameof(user));
            
        _users.Add(user);
        Console.WriteLine($"User {user.Name} added successfully");
    }
    
    public User GetUser(int id)
    {
        return _users.FirstOrDefault(u => u.Id == id);
    }
    
    public List<User> GetAllUsers()
    {
        return _users.ToList();
    }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    
    public User(int id, string name, string email)
    {
        Id = id;
        Name = name;
        Email = email;
    }
    
    public override string ToString()
    {
        return $"User(Id: {Id}, Name: {Name}, Email: {Email})";
    }
}

۷۵. Nullable Reference Types در C# چیست؟

پاسخ:

Nullable Reference Types قابلیتی در C# 8.0 است که به شما اجازه می‌دهد تا مشخص کنید که آیا یک reference type می‌تواند null باشد یا خیر. این قابلیت به جلوگیری از NullReferenceException کمک می‌کند و کیفیت و ایمنی کد را بهبود می‌بخشد.

مزایای Nullable Reference Types:
مثال‌های Nullable Reference Types:
#nullable enable // فعال کردن nullable reference types

using System;
using System.Collections.Generic;

public class NullableReferenceExample
{
    // Non-nullable string
    public string Name { get; set; } = string.Empty;
    
    // Nullable string
    public string? MiddleName { get; set; }
    
    // Non-nullable list
    public List<string> Tags { get; set; } = new();
    
    // Nullable list
    public List<string>? OptionalTags { get; set; }
    
    public NullableReferenceExample(string name)
    {
        Name = name; // OK - non-nullable assigned
    }
    
    public void ProcessName(string name, string? middleName)
    {
        // OK - name is non-nullable
        Console.WriteLine($"Name length: {name.Length}");
        
        // Warning - middleName might be null
        // Console.WriteLine($"Middle name length: {middleName.Length}");
        
        // OK - null check before use
        if (middleName != null)
        {
            Console.WriteLine($"Middle name length: {middleName.Length}");
        }
        
        // OK - using null-conditional operator
        Console.WriteLine($"Middle name length: {middleName?.Length ?? 0}");
    }
    
    public string GetDisplayName()
    {
        // OK - Name is non-nullable
        if (MiddleName != null)
        {
            return $"{Name} {MiddleName}";
        }
        return Name;
    }
    
    // Method that might return null
    public string? FindTag(string searchTag)
    {
        return Tags.FirstOrDefault(tag => tag.Contains(searchTag));
    }
    
    // Method that guarantees non-null return
    public string GetFirstTagOrDefault()
    {
        return Tags.FirstOrDefault() ?? "No tags";
    }
    
    public static void DemonstrateNullableReferences()
    {
        Console.WriteLine("=== Nullable Reference Types Examples ===");
        
        // Creating instances
        var person1 = new NullableReferenceExample("احمد محمدی");
        person1.MiddleName = "علی";
        person1.Tags.AddRange(new[] { "developer", "csharp", "dotnet" });
        
        var person2 = new NullableReferenceExample("فاطمه احمدی");
        // MiddleName remains null
        person2.Tags.Add("designer");
        
        Console.WriteLine($"Person 1: {person1.GetDisplayName()}");
        Console.WriteLine($"Person 2: {person2.GetDisplayName()}");
        
        // Testing methods
        person1.ProcessName("Test Name", "Test Middle");
        person1.ProcessName("Test Name", null);
        
        // Finding tags
        string? foundTag = person1.FindTag("dev");
        if (foundTag != null)
        {
            Console.WriteLine($"Found tag: {foundTag}");
        }
        else
        {
            Console.WriteLine("Tag not found");
        }
        
        // Safe tag access
        string firstTag = person1.GetFirstTagOrDefault();
        Console.WriteLine($"First tag: {firstTag}");
        
        // Null-forgiving operator (use with caution!)
        string definitelyNotNull = person1.FindTag("csharp")!; // We know it exists
        Console.WriteLine($"Definitely not null: {definitelyNotNull}");
    }
}

// Example with nullable attributes
public class ValidationService
{
    // Method that throws if parameter is null
    public static void ValidateNotNull([NotNull] string? value, string paramName)
    {
        if (value == null)
            throw new ArgumentNullException(paramName);
    }
    
    // Method that returns true if value is not null
    public static bool TryGetValue(string? input, [NotNullWhen(true)] out string? value)
    {
        if (!string.IsNullOrEmpty(input))
        {
            value = input;
            return true;
        }
        
        value = null;
        return false;
    }
    
    // Method that might return null
    [return: MaybeNull]
    public static T GetValueOrDefault<T>(Dictionary<string, T> dict, string key)
    {
        dict.TryGetValue(key, out T value);
        return value;
    }
}

#nullable disable // غیرفعال کردن nullable reference types

۷۶. Top-level Programs در C# چیست؟

پاسخ:

Top-level Programs قابلیتی در C# 9.0 است که به شما اجازه می‌دهد تا کد اجرایی را مستقیماً در فایل بنویسید بدون نیاز به تعریف کلاس Program و متد Main. این کار برای ساده‌سازی برنامه‌های کوچک و اسکریپت‌ها طراحی شده است و تجربه یادگیری را برای مبتدیان بهبود می‌بخشد.

مزایای Top-level Programs:
مقایسه Traditional و Top-level:
// Traditional Program (C# 1.0+)
using System;
using System.Threading.Tasks;

namespace MyApplication
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            
            if (args.Length > 0)
            {
                Console.WriteLine($"Arguments: {string.Join(", ", args)}");
            }
            
            await DoSomeWorkAsync();
            
            Console.WriteLine("Program completed!");
        }
        
        static async Task DoSomeWorkAsync()
        {
            Console.WriteLine("Starting async work...");
            await Task.Delay(1000);
            Console.WriteLine("Async work completed!");
        }
    }
}

// Top-level Program (C# 9.0+)
using System;
using System.Threading.Tasks;

Console.WriteLine("Hello World!");

if (args.Length > 0)
{
    Console.WriteLine($"Arguments: {string.Join(", ", args)}");
}

await DoSomeWorkAsync();

Console.WriteLine("Program completed!");

// Local functions can be defined
static async Task DoSomeWorkAsync()
{
    Console.WriteLine("Starting async work...");
    await Task.Delay(1000);
    Console.WriteLine("Async work completed!");
}

// You can also define classes and other types
public class Helper
{
    public static void DoSomething()
    {
        Console.WriteLine("Helper method called!");
    }
}

۷۷. Init-only Properties در C# چیست؟

پاسخ:

Init-only Properties قابلیتی در C# 9.0 است که به شما اجازه می‌دهد تا properties را فقط در زمان مقداردهی اولیه (initialization) تنظیم کنید. این properties پس از ساخت شیء قابل تغییر نیستند و به ایجاد immutable objects کمک می‌کنند.

مزایای Init-only Properties:
مثال‌های Init-only Properties:
using System;
using System.Collections.Generic;

// Simple class with init-only properties
public class Person
{
    public string FirstName { get; init; } = string.Empty;
    public string LastName { get; init; } = string.Empty;
    public int Age { get; init; }
    public DateTime BirthDate { get; init; }
    
    // Computed property (read-only)
    public string FullName => $"{FirstName} {LastName}";
    
    // Constructor is optional with init-only properties
    public Person() { }
    
    public Person(string firstName, string lastName, int age)
    {
        FirstName = firstName;
        LastName = lastName;
        Age = age;
        BirthDate = DateTime.Now.AddYears(-age);
    }
}

// Complex class with validation
public class BankAccount
{
    public string AccountNumber { get; init; } = string.Empty;
    public string OwnerName { get; init; } = string.Empty;
    public decimal InitialBalance { get; init; }
    public DateTime CreatedDate { get; init; } = DateTime.Now;
    public List<string> Tags { get; init; } = new();
    
    // Private field for current balance (mutable)
    private decimal _currentBalance;
    
    public decimal CurrentBalance 
    { 
        get => _currentBalance;
        private set => _currentBalance = value;
    }
    
    // Constructor with validation
    public BankAccount()
    {
        _currentBalance = InitialBalance;
    }
    
    // Method to modify mutable state
    public void Deposit(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("Amount must be positive");
            
        CurrentBalance += amount;
        Console.WriteLine($"Deposited {amount:C}. New balance: {CurrentBalance:C}");
    }
    
    public void Withdraw(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("Amount must be positive");
        if (amount > CurrentBalance)
            throw new InvalidOperationException("Insufficient funds");
            
        CurrentBalance -= amount;
        Console.WriteLine($"Withdrew {amount:C}. New balance: {CurrentBalance:C}");
    }
    
    public override string ToString()
    {
        return $"Account {AccountNumber}: {OwnerName}, Balance: {CurrentBalance:C}";
    }
}

// Record with init-only properties (records use init by default)
public record Product(string Name, decimal Price, string Category)
{
    public List<string> Features { get; init; } = new();
    public bool IsAvailable { get; init; } = true;
}

public class InitOnlyExamples
{
    public static void DemonstrateInitOnlyProperties()
    {
        Console.WriteLine("=== Init-only Properties Examples ===");
        
        // Creating objects with object initializer
        var person1 = new Person
        {
            FirstName = "احمد",
            LastName = "محمدی", 
            Age = 30,
            BirthDate = new DateTime(1993, 5, 15)
        };
        
        Console.WriteLine($"Person 1: {person1.FullName}, Age: {person1.Age}");
        
        // Creating objects with constructor
        var person2 = new Person("فاطمه", "احمدی", 25);
        Console.WriteLine($"Person 2: {person2.FullName}, Age: {person2.Age}");
        
        // Attempting to modify init-only property (compile error)
        // person1.FirstName = "علی"; // Error: Init-only property can only be assigned in object initializer
        
        // Bank account example
        var account = new BankAccount
        {
            AccountNumber = "ACC-001",
            OwnerName = "احمد محمدی",
            InitialBalance = 1000m,
            Tags = { "premium", "savings" }
        };
        
        Console.WriteLine($"\nCreated: {account}");
        
        // Modifying mutable state
        account.Deposit(500m);
        account.Withdraw(200m);
        
        Console.WriteLine($"Final: {account}");
        
        // Record with init-only properties
        var product = new Product("لپ‌تاپ گیمینگ", 1500m, "Electronics")
        {
            Features = { "16GB RAM", "RTX 4060", "1TB SSD" },
            IsAvailable = true
        };
        
        Console.WriteLine($"\nProduct: {product}");
        Console.WriteLine($"Features: [{string.Join(", ", product.Features)}]");
        
        // Creating modified copy with records
        var discountedProduct = product with { Price = 1200m };
        Console.WriteLine($"Discounted: {discountedProduct}");
        
        // Demonstrating immutability
        Console.WriteLine("\n--- Demonstrating Immutability ---");
        
        var originalPerson = new Person
        {
            FirstName = "علی",
            LastName = "رضایی",
            Age = 28
        };
        
        // Cannot modify - this would be a compile error:
        // originalPerson.Age = 29;
        
        // Instead, create a new instance (if using records, you could use 'with')
        var updatedPerson = new Person
        {
            FirstName = originalPerson.FirstName,
            LastName = originalPerson.LastName,
            Age = 29,
            BirthDate = originalPerson.BirthDate
        };
        
        Console.WriteLine($"Original: {originalPerson.FullName}, Age: {originalPerson.Age}");
        Console.WriteLine($"Updated: {updatedPerson.FullName}, Age: {updatedPerson.Age}");
    }
}

۷۸. Target-typed New Expressions در C# چیست؟

پاسخ:

Target-typed New Expressions قابلیتی در C# 9.0 است که به شما اجازه می‌دهد تا از کلمه کلیدی new بدون مشخص کردن نوع استفاده کنید زمانی که نوع از context قابل استنتاج باشد. این کار به کاهش تکرار کد و بهبود خوانایی کمک می‌کند.

مزایای Target-typed New:
مثال‌های Target-typed New:
using System;
using System.Collections.Generic;

public class TargetTypedNewExamples
{
    public class Person
    {
        public string Name { get; set; } = string.Empty;
        public int Age { get; set; }
        
        public Person() { }
        
        public Person(string name, int age)
        {
            Name = name;
            Age = age;
        }
        
        public override string ToString() => $"{Name} ({Age})";
    }
    
    public class Order
    {
        public int Id { get; set; }
        public List<string> Items { get; set; } = new();
        public DateTime OrderDate { get; set; }
        
        public Order(int id)
        {
            Id = id;
            OrderDate = DateTime.Now;
        }
    }
    
    public static void DemonstrateTargetTypedNew()
    {
        Console.WriteLine("=== Target-typed New Expressions ===");
        
        // Traditional way (before C# 9)
        Person person1 = new Person("احمد محمدی", 30);
        List<string> traditionalList = new List<string> { "item1", "item2" };
        Dictionary<string, int> traditionalDict = new Dictionary<string, int>();
        
        // Target-typed new (C# 9+)
        Person person2 = new("فاطمه احمدی", 25);
        List<string> modernList = new() { "item1", "item2", "item3" };
        Dictionary<string, int> modernDict = new();
        
        Console.WriteLine($"Person 1: {person1}");
        Console.WriteLine($"Person 2: {person2}");
        Console.WriteLine($"Modern list count: {modernList.Count}");
        Console.WriteLine($"Modern dict count: {modernDict.Count}");
        
        // In method parameters
        ProcessPerson(new("علی رضایی", 28));
        ProcessList(new() { "apple", "banana", "orange" });
        
        // In array initialization
        Person[] people = {
            new("Person 1", 20),
            new("Person 2", 25),
            new("Person 3", 30)
        };
        
        Console.WriteLine($"\nPeople array:");
        foreach (var person in people)
        {
            Console.WriteLine($"  {person}");
        }
        
        // In property initialization
        var order = new Order(1)
        {
            Items = new() { "لپ‌تاپ", "موس", "کیبورد" }
        };
        
        Console.WriteLine($"\nOrder {order.Id} items:");
        foreach (var item in order.Items)
        {
            Console.WriteLine($"  - {item}");
        }
        
        // Complex generic types
        Dictionary<string, List<Person>> groups = new()
        {
            ["Developers"] = new()
            {
                new("احمد", 30),
                new("فاطمه", 25)
            },
            ["Designers"] = new()
            {
                new("علی", 28),
                new("زهرا", 26)
            }
        };
        
        Console.WriteLine("\nGroups:");
        foreach (var group in groups)
        {
            Console.WriteLine($"  {group.Key}:");
            foreach (var person in group.Value)
            {
                Console.WriteLine($"    - {person}");
            }
        }
        
        // In return statements
        Person GetDefaultPerson() => new("Default User", 0);
        List<string> GetDefaultItems() => new() { "default1", "default2" };
        
        var defaultPerson = GetDefaultPerson();
        var defaultItems = GetDefaultItems();
        
        Console.WriteLine($"\nDefault person: {defaultPerson}");
        Console.WriteLine($"Default items: [{string.Join(", ", defaultItems)}]");
        
        // Conditional expressions
        bool useEmptyList = true;
        List<int> numbers = useEmptyList ? new() : new() { 1, 2, 3, 4, 5 };
        Console.WriteLine($"Numbers count: {numbers.Count}");
        
        // With var (type still inferred from right side)
        var autoList = new List<string> { "auto1", "auto2" }; // Traditional
        // var targetList = new() { "target1", "target2" }; // This won't work - can't infer type
        
        // But this works:
        List<string> targetList = new() { "target1", "target2" };
        Console.WriteLine($"Target list: [{string.Join(", ", targetList)}]");
    }
    
    private static void ProcessPerson(Person person)
    {
        Console.WriteLine($"Processing: {person}");
    }
    
    private static void ProcessList(List<string> items)
    {
        Console.WriteLine($"Processing list with {items.Count} items");
    }
}

۷۹. Switch Expressions در C# چیست؟

پاسخ:

Switch Expressions قابلیتی در C# 8.0 است که سینتکس مختصرتر و قدرتمندتری برای switch statements ارائه می‌دهد. این expressions مقدار برمی‌گردانند و می‌توانند در pattern matching استفاده شوند. آن‌ها کد را خواناتر و مختصرتر می‌کنند.

مزایای Switch Expressions:
مثال‌های Switch Expressions:
using System;

public class SwitchExpressionExamples
{
    public enum DayOfWeek
    {
        Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
    }
    
    public enum Season
    {
        Spring, Summer, Autumn, Winter
    }
    
    public class Shape
    {
        public virtual double Area => 0;
    }
    
    public class Circle : Shape
    {
        public double Radius { get; set; }
        public Circle(double radius) => Radius = radius;
        public override double Area => 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 Area => Width * Height;
    }
    
    public class Triangle : Shape
    {
        public double Base { get; set; }
        public double Height { get; set; }
        public Triangle(double @base, double height)
        {
            Base = @base;
            Height = height;
        }
        public override double Area => 0.5 * Base * Height;
    }
    
    public static void DemonstrateSwitchExpressions()
    {
        Console.WriteLine("=== Switch Expressions Examples ===");
        
        // Basic switch expression
        static string GetDayType(DayOfWeek day) => day switch
        {
            DayOfWeek.Monday or DayOfWeek.Tuesday or DayOfWeek.Wednesday 
                or DayOfWeek.Thursday or DayOfWeek.Friday => "Weekday",
            DayOfWeek.Saturday or DayOfWeek.Sunday => "Weekend",
            _ => "Unknown"
        };
        
        // Test day types
        Console.WriteLine("Day types:");
        foreach (DayOfWeek day in Enum.GetValues<DayOfWeek>())
        {
            Console.WriteLine($"  {day}: {GetDayType(day)}");
        }
        
        // Switch with pattern matching
        static string DescribeNumber(int number) => number switch
        {
            0 => "Zero",
            > 0 and <= 10 => "Small positive",
            > 10 and <= 100 => "Medium positive",
            > 100 => "Large positive",
            < 0 and >= -10 => "Small negative",
            < -10 and >= -100 => "Medium negative",
            < -100 => "Large negative"
        };
        
        // Test number descriptions
        Console.WriteLine("\nNumber descriptions:");
        int[] testNumbers = { 0, 5, 15, 150, -5, -15, -150 };
        foreach (int num in testNumbers)
        {
            Console.WriteLine($"  {num}: {DescribeNumber(num)}");
        }
        
        // Switch with object patterns
        static string DescribeShape(Shape shape) => shape switch
        {
            Circle { Radius: > 10 } => "Large circle",
            Circle { Radius: <= 5 } => "Small circle",
            Circle => "Medium circle",
            Rectangle { Width: var w, Height: var h } when w == h => "Square",
            Rectangle { Width: > 10, Height: > 10 } => "Large rectangle",
            Rectangle => "Rectangle",
            Triangle { Base: > 0, Height: > 0 } => "Valid triangle",
            null => "No shape",
            _ => "Unknown shape"
        };
        
        // Test shapes
        Console.WriteLine("\nShape descriptions:");
        Shape[] shapes = {
            new Circle(3),
            new Circle(12),
            new Rectangle(5, 5),
            new Rectangle(8, 12),
            new Triangle(6, 4),
            null
        };
        
        foreach (var shape in shapes)
        {
            string description = DescribeShape(shape);
            double area = shape?.Area ?? 0;
            Console.WriteLine($"  {shape?.GetType().Name ?? "null"}: {description}, Area: {area:F2}");
        }
        
        // Tuple patterns
        static string GetQuadrant(int x, int y) => (x, y) switch
        {
            (0, 0) => "Origin",
            (var a, var b) when a > 0 && b > 0 => "First quadrant",
            (var a, var b) when a < 0 && b > 0 => "Second quadrant",
            (var a, var b) when a < 0 && b < 0 => "Third quadrant",
            (var a, var b) when a > 0 && b < 0 => "Fourth quadrant",
            (_, 0) => "On X-axis",
            (0, _) => "On Y-axis"
        };
        
        // Test quadrants
        Console.WriteLine("\nQuadrant examples:");
        (int, int)[] points = { (0, 0), (5, 3), (-2, 4), (-3, -1), (2, -5), (0, 7), (4, 0) };
        foreach (var (x, y) in points)
        {
            Console.WriteLine($"  ({x}, {y}): {GetQuadrant(x, y)}");
        }
        
        // Complex expression with multiple patterns
        static string AnalyzeData(object data) => data switch
        {
            null => "No data",
            string s when string.IsNullOrEmpty(s) => "Empty string",
            string s when s.Length < 10 => $"Short string: '{s}'",
            string s => $"Long string ({s.Length} chars)",
            int i when i == 0 => "Zero integer",
            int i when i > 0 => $"Positive integer: {i}",
            int i => $"Negative integer: {i}",
            double d => $"Double: {d:F2}",
            bool b => $"Boolean: {b}",
            Array arr => $"Array with {arr.Length} elements",
            _ => $"Unknown type: {data.GetType().Name}"
        };
        
        // Test data analysis
        Console.WriteLine("\nData analysis:");
        object[] testData = {
            null,
            "",
            "Hello",
            "This is a longer string",
            0,
            42,
            -17,
            3.14159,
            true,
            new int[] { 1, 2, 3, 4, 5 },
            DateTime.Now
        };
        
        foreach (var data in testData)
        {
            Console.WriteLine($"  {AnalyzeData(data)}");
        }
    }
}

۸۰. Using Declarations در C# چیست؟

پاسخ:

Using Declarations قابلیتی در C# 8.0 است که به شما اجازه می‌دهد تا منابع IDisposable را به شکل مختصرتری مدیریت کنید. به جای استفاده از بلوک using، می‌توانید متغیر را با using تعریف کنید و آن در پایان scope خودکار dispose می‌شود.

مزایای Using Declarations:
مقایسه Using Statement و Using Declaration:
using System;
using System.IO;
using System.Threading.Tasks;

public class UsingDeclarationExamples
{
    // Traditional using statements (nested)
    public static void TraditionalUsingExample()
    {
        Console.WriteLine("=== Traditional Using Statements ===");
        
        using (var fileStream = new FileStream("temp1.txt", FileMode.Create))
        {
            using (var writer = new StreamWriter(fileStream))
            {
                writer.WriteLine("Hello from traditional using!");
                writer.WriteLine("This creates nested blocks.");
                
                using (var reader = new StringReader("Some text to read"))
                {
                    string line = reader.ReadLine();
                    writer.WriteLine($"Read: {line}");
                }
            }
        } // All resources disposed here
        
        Console.WriteLine("Traditional using completed");
    }
    
    // Modern using declarations (flat)
    public static void ModernUsingExample()
    {
        Console.WriteLine("\n=== Modern Using Declarations ===");
        
        using var fileStream = new FileStream("temp2.txt", FileMode.Create);
        using var writer = new StreamWriter(fileStream);
        using var reader = new StringReader("Some text to read");
        
        writer.WriteLine("Hello from using declarations!");
        writer.WriteLine("This creates flat, readable code.");
        
        string line = reader.ReadLine();
        writer.WriteLine($"Read: {line}");
        
        // All resources will be disposed at the end of the method
        Console.WriteLine("Modern using completed");
    }
    
    // Mixed approach
    public static void MixedUsingExample()
    {
        Console.WriteLine("\n=== Mixed Using Approach ===");
        
        using var fileStream = new FileStream("temp3.txt", FileMode.Create);
        using var writer = new StreamWriter(fileStream);
        
        writer.WriteLine("Starting mixed approach...");
        
        // Sometimes you still need traditional using for specific scoping
        using (var tempReader = new StringReader("Temporary data"))
        {
            string tempData = tempReader.ReadLine();
            writer.WriteLine($"Temp data: {tempData}");
        } // tempReader disposed here
        
        writer.WriteLine("Continuing after temp reader...");
        
        // fileStream and writer disposed at end of method
    }
    
    // Async example with using declarations
    public static async Task AsyncUsingExample()
    {
        Console.WriteLine("\n=== Async Using Example ===");
        
        using var fileStream = new FileStream("temp4.txt", FileMode.Create);
        using var writer = new StreamWriter(fileStream);
        
        await writer.WriteLineAsync("Starting async operations...");
        
        // Simulate async work
        for (int i = 1; i <= 5; i++)
        {
            await Task.Delay(100);
            await writer.WriteLineAsync($"Async operation {i} completed");
        }
        
        await writer.WriteLineAsync("All async operations completed");
        
        // Resources disposed when method ends
        Console.WriteLine("Async using completed");
    }
    
    // Custom disposable class for demonstration
    public class CustomResource : IDisposable
    {
        private readonly string _name;
        private bool _disposed = false;
        
        public CustomResource(string name)
        {
            _name = name;
            Console.WriteLine($"  {_name} created");
        }
        
        public void DoWork()
        {
            if (_disposed)
                throw new ObjectDisposedException(_name);
                
            Console.WriteLine($"  {_name} doing work...");
        }
        
        public void Dispose()
        {
            if (!_disposed)
            {
                Console.WriteLine($"  {_name} disposed");
                _disposed = true;
            }
        }
    }
    
    public static void CustomResourceExample()
    {
        Console.WriteLine("\n=== Custom Resource Example ===");
        
        using var resource1 = new CustomResource("Resource1");
        using var resource2 = new CustomResource("Resource2");
        using var resource3 = new CustomResource("Resource3");
        
        resource1.DoWork();
        resource2.DoWork();
        resource3.DoWork();
        
        Console.WriteLine("All resources created and used");
        
        // Resources will be disposed in reverse order:
        // Resource3, Resource2, Resource1
    }
    
    // Conditional using declarations
    public static void ConditionalUsingExample(bool useFile)
    {
        Console.WriteLine("\n=== Conditional Using Example ===");
        
        TextWriter writer;
        
        if (useFile)
        {
            using var fileStream = new FileStream("conditional.txt", FileMode.Create);
            using var streamWriter = new StreamWriter(fileStream);
            writer = streamWriter;
            
            writer.WriteLine("Writing to file");
            writer.WriteLine("Using declarations in conditional scope");
            
            // fileStream and streamWriter disposed at end of if block
        }
        else
        {
            writer = Console.Out;
            writer.WriteLine("Writing to console");
            writer.WriteLine("No file resources to dispose");
        }
        
        Console.WriteLine("Conditional using completed");
    }
    
    public static async Task DemonstrateUsingDeclarations()
    {
        TraditionalUsingExample();
        ModernUsingExample();
        MixedUsingExample();
        await AsyncUsingExample();
        CustomResourceExample();
        ConditionalUsingExample(true);
        ConditionalUsingExample(false);
        
        // Clean up temp files
        string[] tempFiles = { "temp1.txt", "temp2.txt", "temp3.txt", "temp4.txt", "conditional.txt" };
        foreach (string file in tempFiles)
        {
            if (File.Exists(file))
            {
                File.Delete(file);
                Console.WriteLine($"Deleted {file}");
            }
        }
    }
}

۸۱. Raw String Literals در C# چیست؟

پاسخ:

Raw String Literals قابلیتی در C# 11 است که راهی جدید و راحت برای تعریف رشته‌ها فراهم می‌کند که در آن نیازی به فرار (escaping) کاراکترهای خاص نیست. این قابلیت به ویژه برای رشته‌هایی که حاوی JSON, XML, HTML, SQL یا عبارات منظم هستند، بسیار مفید است.

مزایای Raw String Literals:
مثال Raw String Literals:
using System;

public class RawStringLiteralsExample
{
    public static void Main(string[] args)
    {
        // مثال با JSON
        string json = """
{
    "name": "احمد محمدی",
    "age": 30,
    "isStudent": true
}
""";
        Console.WriteLine("JSON:");
        Console.WriteLine(json);

        // مثال با HTML
        string html = """
<div class="container">
    <h1>Hello, World!</h1>
    <p>This is a paragraph with "quotes".</p>
</div>
""";
        Console.WriteLine("\nHTML:");
        Console.WriteLine(html);

        // استفاده از Interpolated Raw String Literals
        string name = "علی";
        int age = 25;
        string interpolatedJson = $"""
{
    "personName": "{name}",
    "personAge": {age}
}
""";
        Console.WriteLine("\nInterpolated JSON:");
        Console.WriteLine(interpolatedJson);
    }
}

۸۲. Required Members در C# چیست؟

پاسخ:

Required Members قابلیتی در C# 11 است که به شما اجازه می‌دهد تا خصوصیات یا فیلدهایی را علامت‌گذاری کنید که باید در زمان مقداردهی اولیه شیء مقداردهی شوند. این کار با استفاده از کلمه کلیدی required انجام می‌شود و کامپایلر تضمین می‌کند که اعضای required مقداردهی شده‌اند.

مزایای Required Members:
مثال Required Members:
using System;

public class User
{
    public required int Id { get; init; }
    public required string Username { get; set; }
    public string? Email { get; set; } // اختیاری
}

public class RequiredMembersExample
{
    public static void Main(string[] args)
    {
        // ایجاد یک شیء معتبر
        User user1 = new User
        {
            Id = 1,
            Username = "alice_smith",
            Email = "[email protected]"
        };
        Console.WriteLine($"User 1: Id={user1.Id}, Username={user1.Username}, Email={user1.Email}");

        // ایجاد یک شیء معتبر بدون Email
        User user2 = new User
        {
            Id = 2,
            Username = "bob_johnson"
        };
        Console.WriteLine($"User 2: Id={user2.Id}, Username={user2.Username}, Email={user2.Email}");

        // تلاش برای ایجاد شیء بدون مقداردهی عضو required (خطای کامپایل)
        // User user3 = new User { Id = 3 }; // Error: Required member 'User.Username' must be provided in object initializer or constructor.
    }
}

۸۳. Span<T> و Memory<T> در C# چیست؟

پاسخ:

Span<T> و Memory<T> انواع جدیدی در .NET Core هستند که برای کار با حافظه به شکل کارآمد و ایمن طراحی شده‌اند. Span<T> یک ref struct است که نمایانگر یک بخش پیوسته از حافظه است و Memory<T> نسخه heap-allocated آن است که می‌تواند در async methods استفاده شود.

مزایای Span<T> و Memory<T>:
مثال Span<T> و Memory<T>:
using System;
using System.Threading.Tasks;

public class SpanMemoryExample
{
    public static void Main(string[] args)
    {
        // استفاده از Span با stackalloc
        Span<int> numbers = stackalloc int[10];
        for (int i = 0; i < numbers.Length; i++)
        {
            numbers[i] = i * i;
        }
        
        Console.WriteLine("Numbers in Span:");
        foreach (int num in numbers)
        {
            Console.Write($"{num} ");
        }
        Console.WriteLine();

        // استفاده با آرایه موجود
        int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        Span<int> slice = array.AsSpan(2, 5); // عناصر از ایندکس 2 تا 6
        
        Console.WriteLine("Slice of array:");
        foreach (int item in slice)
        {
            Console.Write($"{item} ");
        }
        Console.WriteLine();

        // تغییر مقادیر در slice
        slice[0] = 100;
        Console.WriteLine($"Original array after slice modification: [{string.Join(", ", array)}]");

        // استفاده از Memory در async context
        ProcessMemoryAsync(array.AsMemory()).Wait();
    }

    public static async Task ProcessMemoryAsync(Memory<int> memory)
    {
        await Task.Delay(100);
        
        Span<int> span = memory.Span;
        for (int i = 0; i < span.Length; i++)
        {
            span[i] *= 2;
        }
        
        Console.WriteLine($"Memory after async processing: [{string.Join(", ", memory.ToArray())}]");
    }
}

۸۴. Source Generators در C# چیست؟

پاسخ:

Source Generators قابلیتی در .NET 5 / C# 9.0 است که به توسعه‌دهندگان اجازه می‌دهد تا کدهای C# را در زمان کامپایل تولید کنند. این کد تولید شده به بقیه کد پروژه اضافه می‌شود و در فرآیند کامپایل نهایی شرکت می‌کند بدون نیاز به تغییر کد موجود یا استفاده از Reflection در زمان اجرا.

مزایای Source Generators:
مثال مفهومی Source Generator:
// کد شما
[GenerateToString]
public partial class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// کد تولید شده توسط Source Generator
public partial class Person
{
    public override string ToString()
    {
        return $"Person {{ Name = {Name}, Age = {Age} }}";
    }
}

// استفاده
public class Program
{
    public static void Main(string[] args)
    {
        var person = new Person { Name = "احمد", Age = 30 };
        Console.WriteLine(person.ToString()); // از متد تولید شده استفاده می‌کند
    }
}

۸۵. Primary Constructors در C# چیست؟

پاسخ:

Primary Constructors قابلیتی در C# 12 است که به شما اجازه می‌دهد تا پارامترهای سازنده را مستقیماً در امضای کلاس یا struct تعریف کنید. این پارامترها به طور خودکار به عنوان فیلدهای خصوصی در دسترس قرار می‌گیرند و می‌توانند برای مقداردهی اولیه خصوصیات استفاده شوند.

مزایای Primary Constructors:
مثال Primary Constructors:
using System;

// کلاس با Primary Constructor
public class Person(string firstName, string lastName, int age)
{
    public string FirstName { get; init; } = firstName;
    public string LastName { get; init; } = lastName;
    public int Age { get; init; } = age;

    // استفاده از پارامترهای سازنده اولیه در متدها
    public void DisplayFullName()
    {
        Console.WriteLine($"Full Name: {firstName} {lastName}");
    }

    // سازنده ثانویه
    public Person(string firstName, string lastName) : this(firstName, lastName, 0) { }
}

// Struct با Primary Constructor
public struct Point(int x, int y)
{
    public int X { get; set; } = x;
    public int Y { get; set; } = y;

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

public class PrimaryConstructorExample
{
    public static void Main(string[] args)
    {
        Person p1 = new Person("احمد", "محمدی", 30);
        Console.WriteLine($"Person 1: {p1.FirstName} {p1.LastName}, Age: {p1.Age}");
        p1.DisplayFullName();

        Point pt = new Point(10, 20);
        Console.WriteLine($"Point: {pt}");
    }
}

۸۶. Collection Expressions در C# چیست؟

پاسخ:

Collection Expressions قابلیتی در C# 12 است که راهی جدید و مختصر برای ایجاد مجموعه‌ها ارائه می‌دهد. این قابلیت از سینتکس [...] استفاده می‌کند و شامل Spread operator (..) برای گسترش عناصر مجموعه‌های موجود است.

مزایای Collection Expressions:
مثال Collection Expressions:
using System;
using System.Collections.Generic;

public class CollectionExpressionsExample
{
    public static void Main(string[] args)
    {
        // ایجاد آرایه
        int[] numbers = [1, 2, 3, 4, 5];
        Console.WriteLine($"Numbers: {string.Join(", ", numbers)}");

        // ایجاد List
        List<string> names = ["احمد", "فاطمه", "علی"];
        Console.WriteLine($"Names: {string.Join(", ", names)}");

        // استفاده از Spread operator
        int[] moreNumbers = [6, 7, 8];
        int[] combined = [..numbers, ..moreNumbers, 9, 10];
        Console.WriteLine($"Combined: {string.Join(", ", combined)}");

        // استفاده در آرگومان‌های متد
        PrintNumbers([10, 20, 30]);

        // ایجاد Span
        Span<char> chars = ['H', 'e', 'l', 'l', 'o'];
        Console.WriteLine($"Chars: {new string(chars)}");
    }

    public static void PrintNumbers(IEnumerable<int> nums)
    {
        Console.WriteLine($"Method numbers: {string.Join(", ", nums)}");
    }
}

۸۷. Unsafe Code و Pointers در C# چیست؟

پاسخ:

Unsafe Code قابلیتی در C# است که به شما اجازه می‌دهد تا از pointers و عملیات حافظه سطح پایین استفاده کنید. این کد خارج از کنترل Garbage Collector اجرا می‌شود و برای سناریوهای خاص عملکرد یا تعامل با کتابخانه‌های native استفاده می‌شود.

کاربردهای Unsafe Code:
مثال Unsafe Code:
using System;

public class UnsafeExample
{
    public static unsafe void Main(string[] args)
    {
        // استفاده از stackalloc
        int* numbers = stackalloc int[5];
        
        // مقداردهی آرایه
        for (int i = 0; i < 5; i++)
        {
            numbers[i] = i * i;
        }
        
        // خواندن مقادیر
        Console.WriteLine("Numbers:");
        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine($"numbers[{i}] = {numbers[i]}");
        }
        
        // استفاده از fixed برای آرایه managed
        int[] managedArray = { 1, 2, 3, 4, 5 };
        fixed (int* ptr = managedArray)
        {
            ProcessArray(ptr, managedArray.Length);
        }
        
        Console.WriteLine($"Modified array: [{string.Join(", ", managedArray)}]");
    }
    
    public static unsafe void ProcessArray(int* ptr, int length)
    {
        for (int i = 0; i < length; i++)
        {
            *(ptr + i) *= 2; // ضرب در 2
        }
    }
}

۸۸. P/Invoke در C# چیست؟

پاسخ:

P/Invoke (Platform Invoke) مکانیزمی در .NET است که به شما اجازه می‌دهد تا توابع موجود در کتابخانه‌های native (مانند Win32 API) را از کد managed فراخوانی کنید. این کار با استفاده از DllImport attribute انجام می‌شود و برای تعامل با سیستم عامل یا کتابخانه‌های C/C++ استفاده می‌شود.

کاربردهای P/Invoke:
مثال P/Invoke:
using System;
using System.Runtime.InteropServices;

public class PInvokeExample
{
    // فراخوانی MessageBox از user32.dll
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);
    
    // فراخوانی GetTickCount از kernel32.dll
    [DllImport("kernel32.dll")]
    public static extern uint GetTickCount();
    
    // فراخوانی Beep از kernel32.dll
    [DllImport("kernel32.dll")]
    public static extern bool Beep(uint frequency, uint duration);
    
    public static void Main(string[] args)
    {
        // نمایش MessageBox
        MessageBox(IntPtr.Zero, "سلام از P/Invoke!", "پیام", 0);
        
        // دریافت زمان سیستم
        uint tickCount = GetTickCount();
        Console.WriteLine($"System uptime: {tickCount} milliseconds");
        
        // پخش صدای بیپ
        Console.WriteLine("Playing beep sound...");
        Beep(1000, 500); // فرکانس 1000 هرتز، مدت 500 میلی‌ثانیه
        
        Console.WriteLine("P/Invoke examples completed!");
    }
}

۸۹. Expression Trees در C# چیست؟

پاسخ:

Expression Trees ساختار داده‌ای در .NET است که کد را به صورت درختی از اشیاء نمایش می‌دهد به جای اینکه به صورت کد قابل اجرا کامپایل شود. این قابلیت امکان تجزیه، تغییر و تولید کد در زمان اجرا را فراهم می‌کند و در LINQ to SQL, Entity Framework و ORM ها بسیار استفاده می‌شود.

کاربردهای Expression Trees:
مثال Expression Trees:
using System;
using System.Linq.Expressions;

public class ExpressionTreeExample
{
    public static void Main(string[] args)
    {
        // ایجاد Expression Tree از lambda
        Expression<Func<int, bool>> expr = x => x > 5;
        
        Console.WriteLine($"Expression: {expr}");
        Console.WriteLine($"Body: {expr.Body}");
        Console.WriteLine($"Parameter: {expr.Parameters[0]}");
        
        // کامپایل و اجرای Expression
        Func<int, bool> compiled = expr.Compile();
        Console.WriteLine($"compiled(3): {compiled(3)}"); // False
        Console.WriteLine($"compiled(7): {compiled(7)}"); // True
        
        // ساخت Expression Tree به صورت دستی
        ParameterExpression param = Expression.Parameter(typeof(int), "x");
        BinaryExpression body = Expression.GreaterThan(param, Expression.Constant(10));
        Expression<Func<int, bool>> manualExpr = Expression.Lambda<Func<int, bool>>(body, param);
        
        Console.WriteLine($"Manual Expression: {manualExpr}");
        
        Func<int, bool> manualCompiled = manualExpr.Compile();
        Console.WriteLine($"manualCompiled(8): {manualCompiled(8)}"); // False
        Console.WriteLine($"manualCompiled(15): {manualCompiled(15)}"); // True
        
        // مثال پیچیده‌تر: x => x * x + 2
        ParameterExpression x = Expression.Parameter(typeof(int), "x");
        BinaryExpression multiply = Expression.Multiply(x, x);
        BinaryExpression add = Expression.Add(multiply, Expression.Constant(2));
        Expression<Func<int, int>> complexExpr = Expression.Lambda<Func<int, int>>(add, x);
        
        Console.WriteLine($"Complex Expression: {complexExpr}");
        
        Func<int, int> complexCompiled = complexExpr.Compile();
        Console.WriteLine($"complexCompiled(3): {complexCompiled(3)}"); // 11 (3*3+2)
        Console.WriteLine($"complexCompiled(5): {complexCompiled(5)}"); // 27 (5*5+2)
    }
}

۹۰. Dynamic Programming در C# چیست؟

پاسخ:

Dynamic Programming در C# به استفاده از کلمه کلیدی dynamic اشاره دارد که امکان تعریف متغیرهایی را فراهم می‌کند که نوع آن‌ها در زمان اجرا تعیین می‌شود. این قابلیت type checking را از زمان کامپایل به زمان اجرا منتقل می‌کند و برای تعامل با COM objects، reflection و سناریوهای متا-برنامه‌نویسی استفاده می‌شود.

کاربردهای Dynamic:
مثال Dynamic Programming:
using System;
using System.Dynamic;

public class DynamicExample
{
    public static void Main(string[] args)
    {
        // استفاده پایه از dynamic
        dynamic obj = "Hello World";
        Console.WriteLine($"String: {obj}");
        Console.WriteLine($"Length: {obj.Length}");
        
        obj = 42;
        Console.WriteLine($"Integer: {obj}");
        Console.WriteLine($"Double: {obj * 2.5}");
        
        // استفاده از ExpandoObject
        dynamic expando = new ExpandoObject();
        expando.Name = "احمد محمدی";
        expando.Age = 30;
        expando.Greet = new Func<string>(() => $"سلام، من {expando.Name} هستم!");
        
        Console.WriteLine($"Name: {expando.Name}");
        Console.WriteLine($"Age: {expando.Age}");
        Console.WriteLine($"Greeting: {expando.Greet()}");
        
        // اضافه کردن خصوصیت جدید در زمان اجرا
        expando.City = "تهران";
        Console.WriteLine($"City: {expando.City}");
        
        // استفاده با anonymous objects
        var anonymous = new { Name = "فاطمه", Age = 25 };
        dynamic dynamicAnonymous = anonymous;
        Console.WriteLine($"Anonymous Name: {dynamicAnonymous.Name}");
        Console.WriteLine($"Anonymous Age: {dynamicAnonymous.Age}");
        
        // مثال خطا در زمان اجرا
        try
        {
            Console.WriteLine(dynamicAnonymous.NonExistentProperty);
        }
        catch (RuntimeBinderException ex)
        {
            Console.WriteLine($"Runtime Error: {ex.Message}");
        }
    }
}

۹۱. Caller Information Attributes در C# چیست؟

پاسخ:

Caller Information Attributes مجموعه‌ای از attribute ها در C# 5.0 هستند که اطلاعات مربوط به فراخوان‌کننده یک متد را به صورت خودکار در دسترس قرار می‌دهند. این attribute ها شامل CallerMemberName، CallerFilePath و CallerLineNumber هستند و برای logging، debugging و پیاده‌سازی INotifyPropertyChanged بسیار مفید هستند.

انواع Caller Information Attributes:
مثال Caller Information:
using System;
using System.Runtime.CompilerServices;

public class CallerInfoExample
{
    public static void LogMessage(string message,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string filePath = "",
        [CallerLineNumber] int lineNumber = 0)
    {
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {memberName} at {System.IO.Path.GetFileName(filePath)}:{lineNumber}");
        Console.WriteLine($"Message: {message}");
        Console.WriteLine();
    }
    
    public static void Method1()
    {
        LogMessage("This is from Method1");
    }
    
    public static void Method2()
    {
        LogMessage("This is from Method2");
    }
    
    // مثال برای INotifyPropertyChanged
    public class Person
    {
        private string _name = "";
        
        public string Name
        {
            get => _name;
            set => SetProperty(ref _name, value);
        }
        
        protected void SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
        {
            if (!Equals(field, value))
            {
                field = value;
                Console.WriteLine($"Property '{propertyName}' changed to: {value}");
            }
        }
    }
    
    public static void Main(string[] args)
    {
        Console.WriteLine("=== Caller Information Examples ===");
        
        LogMessage("Starting application");
        Method1();
        Method2();
        
        // مثال با Person
        var person = new Person();
        person.Name = "احمد محمدی";
        person.Name = "علی رضایی";
    }
}

۹۲. Weak References در C# چیست؟

پاسخ:

Weak References مرجعی به یک شیء است که مانع از garbage collection آن شیء نمی‌شود. این نوع مرجع برای سناریوهایی استفاده می‌شود که می‌خواهید به یک شیء دسترسی داشته باشید اما نمی‌خواهید مانع آزادسازی حافظه آن شوید. WeakReference برای پیاده‌سازی cache ها و جلوگیری از memory leak مفید است.

کاربردهای Weak References:
مثال Weak References:
using System;

public class LargeObject
{
    private byte[] _data;
    public string Name { get; set; }
    
    public LargeObject(string name, int size = 1024 * 1024) // 1MB default
    {
        Name = name;
        _data = new byte[size];
        Console.WriteLine($"LargeObject '{name}' created with {size} bytes");
    }
    
    ~LargeObject()
    {
        Console.WriteLine($"LargeObject '{Name}' finalized");
    }
    
    public void DoSomething()
    {
        Console.WriteLine($"LargeObject '{Name}' is doing something");
    }
}

public class WeakReferenceExample
{
    public static void Main(string[] args)
    {
        Console.WriteLine("=== Weak Reference Examples ===");
        
        // ایجاد شیء و weak reference
        var largeObj = new LargeObject("Object1");
        WeakReference weakRef = new WeakReference(largeObj);
        
        Console.WriteLine($"Is target alive? {weakRef.IsAlive}");
        
        // استفاده از weak reference
        if (weakRef.Target is LargeObject target)
        {
            target.DoSomething();
        }
        
        // حذف strong reference
        largeObj = null;
        
        Console.WriteLine($"After nulling strong reference - Is target alive? {weakRef.IsAlive}");
        
        // اجبار garbage collection
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        
        Console.WriteLine($"After GC - Is target alive? {weakRef.IsAlive}");
        
        // تلاش برای استفاده پس از GC
        if (weakRef.Target is LargeObject aliveTarget)
        {
            aliveTarget.DoSomething();
        }
        else
        {
            Console.WriteLine("Target has been garbage collected");
        }
        
        // مثال با cache
        Console.WriteLine("\n--- Cache Example ---");
        var cache = new SimpleCache();
        
        cache.Store("key1", new LargeObject("CachedObject1"));
        cache.Store("key2", new LargeObject("CachedObject2"));
        
        // استفاده از cache
        var cached1 = cache.Get("key1");
        cached1?.DoSomething();
        
        // اجبار GC
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        
        // تلاش برای دریافت پس از GC
        var cached2 = cache.Get("key1");
        if (cached2 == null)
        {
            Console.WriteLine("Cached object was garbage collected");
        }
    }
}

public class SimpleCache
{
    private readonly System.Collections.Generic.Dictionary<string, WeakReference> _cache = new();
    
    public void Store(string key, object value)
    {
        _cache[key] = new WeakReference(value);
        Console.WriteLine($"Stored object with key '{key}' in cache");
    }
    
    public T Get<T>(string key) where T : class
    {
        if (_cache.TryGetValue(key, out WeakReference weakRef))
        {
            if (weakRef.Target is T target)
            {
                Console.WriteLine($"Retrieved object with key '{key}' from cache");
                return target;
            }
            else
            {
                // شیء garbage collect شده، از cache حذف کنیم
                _cache.Remove(key);
                Console.WriteLine($"Object with key '{key}' was garbage collected, removed from cache");
            }
        }
        
        return null;
    }
}

۹۳. Finalizers و Destructors در C# چیست؟

پاسخ:

Finalizers (نهایی‌سازها) متدهای خاصی در C# هستند که توسط Garbage Collector قبل از آزادسازی حافظه یک شیء فراخوانی می‌شوند. آن‌ها با سینتکس ~ClassName() تعریف می‌شوند و برای پاک‌سازی منابع unmanaged (مانند file handles، database connections) استفاده می‌شوند.

نکات مهم Finalizers:
مثال Finalizers و Dispose Pattern:
using System;
using System.IO;

public class ResourceHolder : IDisposable
{
    private FileStream _fileStream;
    private bool _disposed = false;
    
    public ResourceHolder(string fileName)
    {
        _fileStream = new FileStream(fileName, FileMode.CreateNew);
        Console.WriteLine($"ResourceHolder created with file: {fileName}");
    }
    
    // Finalizer (Destructor)
    ~ResourceHolder()
    {
        Console.WriteLine("Finalizer called");
        Dispose(false);
    }
    
    // Public Dispose method
    public void Dispose()
    {
        Console.WriteLine("Dispose called");
        Dispose(true);
        GC.SuppressFinalize(this); // جلوگیری از فراخوانی finalizer
    }
    
    // Protected Dispose method (Dispose Pattern)
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // پاک‌سازی managed resources
                _fileStream?.Dispose();
                Console.WriteLine("Managed resources disposed");
            }
            
            // پاک‌سازی unmanaged resources (اگر وجود داشته باشد)
            Console.WriteLine("Unmanaged resources cleaned up");
            
            _disposed = true;
        }
    }
    
    public void WriteData(string data)
    {
        if (_disposed)
            throw new ObjectDisposedException(nameof(ResourceHolder));
            
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data);
        _fileStream.Write(bytes, 0, bytes.Length);
        Console.WriteLine($"Data written: {data}");
    }
}

public class FinalizerExample
{
    public static void Main(string[] args)
    {
        Console.WriteLine("=== Finalizer and Dispose Pattern Examples ===");
        
        // مثال 1: استفاده صحیح با using
        Console.WriteLine("\n--- Using statement example ---");
        using (var resource1 = new ResourceHolder("test1.txt"))
        {
            resource1.WriteData("Hello from using statement");
        } // Dispose خودکار فراخوانی می‌شود
        
        // مثال 2: استفاده دستی از Dispose
        Console.WriteLine("\n--- Manual Dispose example ---");
        var resource2 = new ResourceHolder("test2.txt");
        resource2.WriteData("Hello from manual dispose");
        resource2.Dispose();
        
        // مثال 3: بدون Dispose (finalizer فراخوانی می‌شود)
        Console.WriteLine("\n--- Without Dispose example ---");
        CreateResourceWithoutDispose();
        
        // اجبار garbage collection برای نمایش finalizer
        Console.WriteLine("\nForcing garbage collection...");
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        
        Console.WriteLine("Main method completed");
        
        // پاک‌سازی فایل‌های تست
        CleanupTestFiles();
    }
    
    private static void CreateResourceWithoutDispose()
    {
        var resource = new ResourceHolder("test3.txt");
        resource.WriteData("Hello without dispose");
        // resource خارج از scope می‌شود اما Dispose فراخوانی نمی‌شود
    }
    
    private static void CleanupTestFiles()
    {
        string[] testFiles = { "test1.txt", "test2.txt", "test3.txt" };
        foreach (string file in testFiles)
        {
            try
            {
                if (File.Exists(file))
                {
                    File.Delete(file);
                    Console.WriteLine($"Deleted test file: {file}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Could not delete {file}: {ex.Message}");
            }
        }
    }
}

۹۴. Thread-Safe Collections در C# چیست؟

پاسخ:

Thread-Safe Collections مجموعه‌هایی در .NET هستند که برای استفاده همزمان توسط چندین thread طراحی شده‌اند. این collections در namespace System.Collections.Concurrent قرار دارند و عملیات thread-safe را بدون نیاز به lock های خارجی فراهم می‌کنند.

انواع Thread-Safe Collections:
مثال Thread-Safe Collections:
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

public class ThreadSafeCollectionsExample
{
    public static async Task Main(string[] args)
    {
        Console.WriteLine("=== Thread-Safe Collections Examples ===");
        
        await ConcurrentDictionaryExample();
        await ConcurrentQueueExample();
        await ConcurrentStackExample();
        await BlockingCollectionExample();
    }
    
    private static async Task ConcurrentDictionaryExample()
    {
        Console.WriteLine("\n--- ConcurrentDictionary Example ---");
        
        var concurrentDict = new ConcurrentDictionary<string, int>();
        
        // اضافه کردن همزمان از چندین task
        var tasks = new Task[5];
        for (int i = 0; i < 5; i++)
        {
            int taskId = i;
            tasks[i] = Task.Run(() =>
            {
                for (int j = 0; j < 10; j++)
                {
                    string key = $"Task{taskId}_Item{j}";
                    concurrentDict.TryAdd(key, taskId * 10 + j);
                }
                Console.WriteLine($"Task {taskId} completed adding items");
            });
        }
        
        await Task.WhenAll(tasks);
        Console.WriteLine($"Total items in dictionary: {concurrentDict.Count}");
        
        // عملیات thread-safe
        concurrentDict.TryUpdate("Task0_Item0", 999, 0);
        concurrentDict.AddOrUpdate("NewKey", 100, (key, oldValue) => oldValue + 1);
        
        Console.WriteLine($"Updated dictionary count: {concurrentDict.Count}");
    }
    
    private static async Task ConcurrentQueueExample()
    {
        Console.WriteLine("\n--- ConcurrentQueue Example ---");
        
        var concurrentQueue = new ConcurrentQueue<string>();
        
        // Producer task
        var producer = Task.Run(async () =>
        {
            for (int i = 0; i < 20; i++)
            {
                concurrentQueue.Enqueue($"Item_{i}");
                Console.WriteLine($"Enqueued: Item_{i}");
                await Task.Delay(50);
            }
        });
        
        // Consumer task
        var consumer = Task.Run(async () =>
        {
            int processedCount = 0;
            while (processedCount < 20)
            {
                if (concurrentQueue.TryDequeue(out string item))
                {
                    Console.WriteLine($"Dequeued: {item}");
                    processedCount++;
                }
                await Task.Delay(100);
            }
        });
        
        await Task.WhenAll(producer, consumer);
        Console.WriteLine($"Remaining items in queue: {concurrentQueue.Count}");
    }
    
    private static async Task ConcurrentStackExample()
    {
        Console.WriteLine("\n--- ConcurrentStack Example ---");
        
        var concurrentStack = new ConcurrentStack<int>();
        
        // Push items from multiple tasks
        var pushTasks = new Task[3];
        for (int i = 0; i < 3; i++)
        {
            int taskId = i;
            pushTasks[i] = Task.Run(() =>
            {
                for (int j = 0; j < 5; j++)
                {
                    int value = taskId * 10 + j;
                    concurrentStack.Push(value);
                    Console.WriteLine($"Pushed: {value}");
                }
            });
        }
        
        await Task.WhenAll(pushTasks);
        
        // Pop items
        Console.WriteLine("Popping items:");
        while (concurrentStack.TryPop(out int item))
        {
            Console.WriteLine($"Popped: {item}");
        }
    }
    
    private static async Task BlockingCollectionExample()
    {
        Console.WriteLine("\n--- BlockingCollection Example ---");
        
        using var blockingCollection = new BlockingCollection<string>(5); // محدود به 5 آیتم
        
        // Producer
        var producer = Task.Run(async () =>
        {
            try
            {
                for (int i = 0; i < 10; i++)
                {
                    string item = $"Product_{i}";
                    blockingCollection.Add(item);
                    Console.WriteLine($"Produced: {item}");
                    await Task.Delay(200);
                }
            }
            finally
            {
                blockingCollection.CompleteAdding();
                Console.WriteLine("Producer completed");
            }
        });
        
        // Consumer
        var consumer = Task.Run(() =>
        {
            try
            {
                foreach (string item in blockingCollection.GetConsumingEnumerable())
                {
                    Console.WriteLine($"Consumed: {item}");
                    Task.Delay(300).Wait(); // شبیه‌سازی پردازش
                }
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("Collection was marked as complete");
            }
            Console.WriteLine("Consumer completed");
        });
        
        await Task.WhenAll(producer, consumer);
    }
}

۹۵. Immutable Collections در C# چیست؟

پاسخ:

Immutable Collections مجموعه‌هایی هستند که پس از ایجاد قابل تغییر نیستند. هر عملیات تغییر یک نسخه جدید از مجموعه را برمی‌گرداند بدون تغییر نسخه اصلی. این collections در System.Collections.Immutable namespace قرار دارند و برای سناریوهای thread-safe و functional programming مفید هستند.

مزایای Immutable Collections:
مثال Immutable Collections:
using System;
using System.Collections.Immutable;
using System.Linq;

public class ImmutableCollectionsExample
{
    public static void Main(string[] args)
    {
        Console.WriteLine("=== Immutable Collections Examples ===");
        
        ImmutableListExample();
        ImmutableDictionaryExample();
        ImmutableSetExample();
        PerformanceExample();
    }
    
    private static void ImmutableListExample()
    {
        Console.WriteLine("\n--- ImmutableList Example ---");
        
        // ایجاد ImmutableList
        var originalList = ImmutableList.Create(1, 2, 3, 4, 5);
        Console.WriteLine($"Original list: [{string.Join(", ", originalList)}]");
        
        // اضافه کردن عنصر (نسخه جدید برمی‌گردد)
        var newList = originalList.Add(6);
        Console.WriteLine($"After Add(6): [{string.Join(", ", newList)}]");
        Console.WriteLine($"Original unchanged: [{string.Join(", ", originalList)}]");
        
        // حذف عنصر
        var removedList = newList.Remove(3);
        Console.WriteLine($"After Remove(3): [{string.Join(", ", removedList)}]");
        
        // اضافه کردن چندین عنصر
        var extendedList = removedList.AddRange(new[] { 7, 8, 9 });
        Console.WriteLine($"After AddRange: [{string.Join(", ", extendedList)}]");
        
        // استفاده از Builder برای عملیات متعدد
        var builder = originalList.ToBuilder();
        builder.Add(10);
        builder.Add(11);
        builder.Remove(2);
        var builtList = builder.ToImmutable();
        Console.WriteLine($"Using Builder: [{string.Join(", ", builtList)}]");
    }
    
    private static void ImmutableDictionaryExample()
    {
        Console.WriteLine("\n--- ImmutableDictionary Example ---");
        
        // ایجاد ImmutableDictionary
        var originalDict = ImmutableDictionary.Create<string, int>()
            .Add("apple", 5)
            .Add("banana", 3)
            .Add("orange", 8);
        
        Console.WriteLine("Original dictionary:");
        foreach (var kvp in originalDict)
        {
            Console.WriteLine($"  {kvp.Key}: {kvp.Value}");
        }
        
        // اضافه کردن کلید جدید
        var newDict = originalDict.Add("grape", 12);
        Console.WriteLine($"\nAfter adding grape: {newDict.Count} items");
        
        // به‌روزرسانی مقدار
        var updatedDict = newDict.SetItem("apple", 10);
        Console.WriteLine($"Apple count updated to: {updatedDict["apple"]}");
        Console.WriteLine($"Original apple count: {originalDict["apple"]}");
        
        // حذف کلید
        var removedDict = updatedDict.Remove("banana");
        Console.WriteLine($"After removing banana: {removedDict.Count} items");
    }
    
    private static void ImmutableSetExample()
    {
        Console.WriteLine("\n--- ImmutableHashSet Example ---");
        
        var originalSet = ImmutableHashSet.Create("red", "green", "blue");
        Console.WriteLine($"Original set: [{string.Join(", ", originalSet)}]");
        
        // اضافه کردن عنصر
        var newSet = originalSet.Add("yellow");
        Console.WriteLine($"After Add yellow: [{string.Join(", ", newSet)}]");
        
        // تلاش برای اضافه کردن عنصر تکراری
        var duplicateSet = newSet.Add("red"); // تغییری ایجاد نمی‌کند
        Console.WriteLine($"After Add red (duplicate): [{string.Join(", ", duplicateSet)}]");
        Console.WriteLine($"Sets are equal: {ReferenceEquals(newSet, duplicateSet)}");
        
        // عملیات مجموعه‌ای
        var otherSet = ImmutableHashSet.Create("blue", "purple", "pink");
        var unionSet = newSet.Union(otherSet);
        var intersectSet = newSet.Intersect(otherSet);
        
        Console.WriteLine($"Union: [{string.Join(", ", unionSet)}]");
        Console.WriteLine($"Intersect: [{string.Join(", ", intersectSet)}]");
    }
    
    private static void PerformanceExample()
    {
        Console.WriteLine("\n--- Performance Comparison ---");
        
        const int itemCount = 10000;
        
        // مقایسه عملکرد با List معمولی
        var watch = System.Diagnostics.Stopwatch.StartNew();
        
        var mutableList = new System.Collections.Generic.List<int>();
        for (int i = 0; i < itemCount; i++)
        {
            mutableList.Add(i);
        }
        watch.Stop();
        Console.WriteLine($"Mutable List creation: {watch.ElapsedMilliseconds} ms");
        
        // ImmutableList با Builder
        watch.Restart();
        var builder = ImmutableList.CreateBuilder<int>();
        for (int i = 0; i < itemCount; i++)
        {
            builder.Add(i);
        }
        var immutableList = builder.ToImmutable();
        watch.Stop();
        Console.WriteLine($"ImmutableList with Builder: {watch.ElapsedMilliseconds} ms");
        
        // ImmutableList بدون Builder (کند)
        watch.Restart();
        var slowImmutableList = ImmutableList<int>.Empty;
        for (int i = 0; i < Math.Min(1000, itemCount); i++) // فقط 1000 آیتم برای جلوگیری از کندی
        {
            slowImmutableList = slowImmutableList.Add(i);
        }
        watch.Stop();
        Console.WriteLine($"ImmutableList without Builder (1000 items): {watch.ElapsedMilliseconds} ms");
        
        Console.WriteLine($"Final counts - Mutable: {mutableList.Count}, Immutable: {immutableList.Count}");
    }
}

۹۶. Minimal APIs در .NET چیست؟

پاسخ:

Minimal APIs قابلیتی در .NET 6+ است که راهی ساده و مختصر برای ایجاد HTTP APIs فراهم می‌کند بدون نیاز به کنترلرها و boilerplate code زیاد. این approach برای microservices، prototyping و APIs ساده بسیار مناسب است و کد کمتری نسبت به روش سنتی ASP.NET Core نیاز دارد.

مزایای Minimal APIs:
مثال Minimal APIs:
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

// اضافه کردن سرویس‌ها
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure pipeline
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

// Simple GET endpoint
app.MapGet("/", () => "Hello Minimal API!");

// GET with parameter
app.MapGet("/hello/{name}", (string name) => $"Hello, {name}!");

// GET with query parameter
app.MapGet("/greet", (string? name) => 
    Results.Ok($"Greetings, {name ?? "Anonymous"}!"));

// POST endpoint
app.MapPost("/users", (User user) => 
{
    // شبیه‌سازی ذخیره در دیتابیس
    user.Id = Random.Shared.Next(1, 1000);
    return Results.Created($"/users/{user.Id}", user);
});

// GET with route parameter
app.MapGet("/users/{id:int}", (int id) => 
{
    // شبیه‌سازی دریافت از دیتابیس
    var user = new User { Id = id, Name = $"User{id}", Email = $"user{id}@example.com" };
    return Results.Ok(user);
});

// PUT endpoint
app.MapPut("/users/{id:int}", (int id, User user) => 
{
    user.Id = id;
    // شبیه‌سازی به‌روزرسانی
    return Results.Ok(user);
});

// DELETE endpoint
app.MapDelete("/users/{id:int}", (int id) => 
{
    // شبیه‌سازی حذف
    return Results.NoContent();
});

// Endpoint with dependency injection
app.MapGet("/time", (TimeProvider timeProvider) => 
    Results.Ok(new { CurrentTime = timeProvider.GetUtcNow() }));

// Endpoint with validation
app.MapPost("/validate", ([FromBody] User user) => 
{
    if (string.IsNullOrEmpty(user.Name))
        return Results.BadRequest("Name is required");
    
    if (string.IsNullOrEmpty(user.Email))
        return Results.BadRequest("Email is required");
    
    return Results.Ok("Validation passed");
});

// Group endpoints
var usersGroup = app.MapGroup("/api/users");
usersGroup.MapGet("/", () => "All users endpoint");
usersGroup.MapGet("/{id}", (int id) => $"User {id} endpoint");
usersGroup.MapPost("/", (User user) => "Create user endpoint");

// Endpoint with custom response
app.MapGet("/custom", () => 
    Results.Json(new { 
        Message = "Custom response", 
        Timestamp = DateTime.UtcNow,
        Data = new[] { 1, 2, 3, 4, 5 }
    }));

app.Run();

// Model classes
public class User
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public string Email { get; set; } = "";
}

۹۷. Assembly Loading و Reflection در C# چیست؟

پاسخ:

Assembly Loading فرآیند بارگذاری assemblies (فایل‌های .dll یا .exe) در زمان اجرا است و Reflection قابلیتی است که به شما اجازه می‌دهد تا metadata و اعضای انواع را در زمان اجرا بررسی و استفاده کنید. این قابلیت‌ها برای plugin systems، serialization، ORM ها و dependency injection containers استفاده می‌شوند.

کاربردهای Assembly Loading و Reflection:
مثال Assembly Loading و Reflection:
using System;
using System.Reflection;
using System.IO;

// کلاس نمونه برای تست Reflection
public class SampleClass
{
    public string Name { get; set; } = "";
    public int Age { get; set; }
    private string _secret = "Secret Value";
    
    public SampleClass() { }
    
    public SampleClass(string name, int age)
    {
        Name = name;
        Age = age;
    }
    
    public void PublicMethod()
    {
        Console.WriteLine($"Public method called for {Name}");
    }
    
    private void PrivateMethod()
    {
        Console.WriteLine("Private method called");
    }
    
    public string GetInfo()
    {
        return $"Name: {Name}, Age: {Age}";
    }
}

public class ReflectionExample
{
    public static void Main(string[] args)
    {
        Console.WriteLine("=== Assembly Loading and Reflection Examples ===");
        
        BasicReflectionExample();
        AssemblyLoadingExample();
        DynamicObjectCreationExample();
        PrivateMemberAccessExample();
        AttributeReflectionExample();
    }
    
    private static void BasicReflectionExample()
    {
        Console.WriteLine("\n--- Basic Reflection Example ---");
        
        // دریافت Type
        Type sampleType = typeof(SampleClass);
        Console.WriteLine($"Type name: {sampleType.Name}");
        Console.WriteLine($"Full name: {sampleType.FullName}");
        Console.WriteLine($"Assembly: {sampleType.Assembly.GetName().Name}");
        
        // دریافت Properties
        Console.WriteLine("\nProperties:");
        PropertyInfo[] properties = sampleType.GetProperties();
        foreach (PropertyInfo prop in properties)
        {
            Console.WriteLine($"  {prop.Name} ({prop.PropertyType.Name})");
        }
        
        // دریافت Methods
        Console.WriteLine("\nPublic Methods:");
        MethodInfo[] methods = sampleType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
        foreach (MethodInfo method in methods)
        {
            Console.WriteLine($"  {method.Name}");
        }
    }
    
    private static void AssemblyLoadingExample()
    {
        Console.WriteLine("\n--- Assembly Loading Example ---");
        
        // دریافت Assembly فعلی
        Assembly currentAssembly = Assembly.GetExecutingAssembly();
        Console.WriteLine($"Current assembly: {currentAssembly.GetName().Name}");
        
        // دریافت تمام Types در Assembly
        Type[] types = currentAssembly.GetTypes();
        Console.WriteLine($"Types in assembly: {types.Length}");
        
        foreach (Type type in types)
        {
            if (type.IsPublic && type.IsClass)
            {
                Console.WriteLine($"  Public class: {type.Name}");
            }
        }
        
        // بارگذاری Assembly از فایل (اگر وجود داشته باشد)
        try
        {
            // Assembly externalAssembly = Assembly.LoadFrom("ExternalLibrary.dll");
            // Console.WriteLine($"External assembly loaded: {externalAssembly.GetName().Name}");
        }
        catch (FileNotFoundException)
        {
            Console.WriteLine("External assembly not found (this is expected in this example)");
        }
    }
    
    private static void DynamicObjectCreationExample()
    {
        Console.WriteLine("\n--- Dynamic Object Creation Example ---");
        
        Type sampleType = typeof(SampleClass);
        
        // ایجاد شیء با سازنده پیش‌فرض
        object instance1 = Activator.CreateInstance(sampleType);
        Console.WriteLine($"Created instance: {instance1?.GetType().Name}");
        
        // ایجاد شیء با سازنده پارامتردار
        object instance2 = Activator.CreateInstance(sampleType, "احمد محمدی", 30);
        
        // استفاده از Reflection برای تنظیم Properties
        PropertyInfo nameProperty = sampleType.GetProperty("Name");
        PropertyInfo ageProperty = sampleType.GetProperty("Age");
        
        nameProperty?.SetValue(instance1, "فاطمه احمدی");
        ageProperty?.SetValue(instance1, 25);
        
        // فراخوانی متد
        MethodInfo getInfoMethod = sampleType.GetMethod("GetInfo");
        string info1 = (string)getInfoMethod?.Invoke(instance1, null);
        string info2 = (string)getInfoMethod?.Invoke(instance2, null);
        
        Console.WriteLine($"Instance 1: {info1}");
        Console.WriteLine($"Instance 2: {info2}");
    }
    
    private static void PrivateMemberAccessExample()
    {
        Console.WriteLine("\n--- Private Member Access Example ---");
        
        var sample = new SampleClass("تست", 20);
        Type sampleType = typeof(SampleClass);
        
        // دسترسی به فیلد private
        FieldInfo secretField = sampleType.GetField("_secret", BindingFlags.NonPublic | BindingFlags.Instance);
        object secretValue = secretField?.GetValue(sample);
        Console.WriteLine($"Private field value: {secretValue}");
        
        // تغییر مقدار فیلد private
        secretField?.SetValue(sample, "New Secret Value");
        object newSecretValue = secretField?.GetValue(sample);
        Console.WriteLine($"Updated private field: {newSecretValue}");
        
        // فراخوانی متد private
        MethodInfo privateMethod = sampleType.GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
        privateMethod?.Invoke(sample, null);
    }
    
    private static void AttributeReflectionExample()
    {
        Console.WriteLine("\n--- Attribute Reflection Example ---");
        
        // کلاس با Attribute
        Type stringType = typeof(string);
        
        // دریافت Attributes
        object[] attributes = stringType.GetCustomAttributes(false);
        Console.WriteLine($"Attributes on String type: {attributes.Length}");
        
        // مثال با custom attribute
        Type sampleType = typeof(SampleClass);
        MethodInfo[] methods = sampleType.GetMethods();
        
        foreach (MethodInfo method in methods)
        {
            // بررسی Obsolete attribute (اگر وجود داشته باشد)
            if (method.GetCustomAttribute<ObsoleteAttribute>() != null)
            {
                Console.WriteLine($"Method {method.Name} is obsolete");
            }
        }
    }
}

// Custom Attribute برای نمایش
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomInfoAttribute : Attribute
{
    public string Description { get; set; }
    
    public CustomInfoAttribute(string description)
    {
        Description = description;
    }
}

۹۸. Conditional Compilation در C# چیست؟

پاسخ:

Conditional Compilation قابلیتی در C# است که به شما اجازه می‌دهد تا بخش‌هایی از کد را بر اساس شرایط مشخص شده در زمان کامپایل، شامل یا حذف کنید. این کار با استفاده از preprocessor directives مانند #if، #else، #elif و #endif انجام می‌شود و برای ایجاد build های مختلف (Debug/Release) یا پلتفرم‌های مختلف استفاده می‌شود.

کاربردهای Conditional Compilation:
مثال Conditional Compilation:
using System;
using System.Diagnostics;

#define FEATURE_LOGGING
#define FEATURE_CACHING
// #define FEATURE_ANALYTICS // غیرفعال

public class ConditionalCompilationExample
{
    public static void Main(string[] args)
    {
        Console.WriteLine("=== Conditional Compilation Examples ===");
        
        // کد مشترک که همیشه اجرا می‌شود
        Console.WriteLine("Application started");
        
        // کد مخصوص Debug
#if DEBUG
        Console.WriteLine("Debug mode is enabled");
        LogDebugInfo();
#else
        Console.WriteLine("Release mode is enabled");
#endif
        
        // کد مخصوص پلتفرم
#if WINDOWS
        Console.WriteLine("Running on Windows");
        WindowsSpecificCode();
#elif LINUX
        Console.WriteLine("Running on Linux");
        LinuxSpecificCode();
#elif MACOS
        Console.WriteLine("Running on macOS");
        MacOSSpecificCode();
#else
        Console.WriteLine("Running on unknown platform");
#endif
        
        // استفاده از feature flags
#if FEATURE_LOGGING
        LogMessage("Logging feature is enabled");
#endif
        
#if FEATURE_CACHING
        InitializeCache();
#endif
        
#if FEATURE_ANALYTICS
        TrackEvent("Application started");
#else
        Console.WriteLine("Analytics feature is disabled");
#endif
        
        // استفاده از Conditional attribute
        DebugOnlyMethod();
        
        // کد با شرط پیچیده
#if DEBUG && FEATURE_LOGGING
        Console.WriteLine("Debug logging is available");
#endif
        
#if !FEATURE_CACHING
        Console.WriteLine("Caching is disabled, using direct access");
#endif
        
        Console.WriteLine("Application completed");
    }
    
#if DEBUG
    private static void LogDebugInfo()
    {
        Console.WriteLine($"Debug info: Current time = {DateTime.Now}");
        Console.WriteLine($"Debug info: Memory usage = {GC.GetTotalMemory(false)} bytes");
    }
#endif
    
#if WINDOWS
    private static void WindowsSpecificCode()
    {
        Console.WriteLine("Executing Windows-specific functionality");
        // کد مخصوص Windows
    }
#endif
    
#if LINUX
    private static void LinuxSpecificCode()
    {
        Console.WriteLine("Executing Linux-specific functionality");
        // کد مخصوص Linux
    }
#endif
    
#if MACOS
    private static void MacOSSpecificCode()
    {
        Console.WriteLine("Executing macOS-specific functionality");
        // کد مخصوص macOS
    }
#endif
    
#if FEATURE_LOGGING
    private static void LogMessage(string message)
    {
        Console.WriteLine($"[LOG] {DateTime.Now:HH:mm:ss} - {message}");
    }
#endif
    
#if FEATURE_CACHING
    private static void InitializeCache()
    {
        Console.WriteLine("Cache initialized");
        // کد مقداردهی cache
    }
#endif
    
#if FEATURE_ANALYTICS
    private static void TrackEvent(string eventName)
    {
        Console.WriteLine($"Analytics: Event '{eventName}' tracked");
        // کد ارسال به سرویس analytics
    }
#endif
    
    // استفاده از Conditional attribute
    [Conditional("DEBUG")]
    private static void DebugOnlyMethod()
    {
        Console.WriteLine("This method only runs in DEBUG builds");
    }
    
    // مثال کلاس با conditional compilation
    public class Logger
    {
#if DEBUG
        public static void Debug(string message)
        {
            Console.WriteLine($"[DEBUG] {message}");
        }
#endif
        
        public static void Info(string message)
        {
            Console.WriteLine($"[INFO] {message}");
        }
        
#if FEATURE_LOGGING
        public static void Verbose(string message)
        {
            Console.WriteLine($"[VERBOSE] {message}");
        }
#endif
    }
}

// مثال کلاس کامل با conditional compilation
#if FEATURE_ADVANCED_MATH
public class AdvancedMath
{
    public static double CalculateComplexFunction(double x)
    {
        return Math.Pow(x, 3) + Math.Sin(x) * Math.Cos(x);
    }
    
    public static double[] SolveQuadratic(double a, double b, double c)
    {
        double discriminant = b * b - 4 * a * c;
        if (discriminant < 0)
            return new double[0]; // No real solutions
        
        double sqrtDiscriminant = Math.Sqrt(discriminant);
        return new double[]
        {
            (-b + sqrtDiscriminant) / (2 * a),
            (-b - sqrtDiscriminant) / (2 * a)
        };
    }
}
#endif

۹۹. Global Assembly Attributes در C# چیست؟

پاسخ:

Global Assembly Attributes مجموعه‌ای از attribute ها هستند که metadata و اطلاعات کلی در مورد یک assembly ارائه می‌دهند. این attribute ها معمولاً در فایل AssemblyInfo.cs تعریف می‌شوند و شامل اطلاعاتی مانند نسخه، نویسنده، توضیحات و تنظیمات امنیتی assembly هستند.

انواع مهم Assembly Attributes:
مثال Global Assembly Attributes:
// معمولاً در فایل AssemblyInfo.cs یا در بالای Program.cs
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

// اطلاعات کلی assembly
[assembly: AssemblyTitle("نمونه برنامه C#")]
[assembly: AssemblyDescription("این یک برنامه نمونه برای نمایش Assembly Attributes است")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyCompany("شرکت نمونه")]
[assembly: AssemblyProduct("محصول نمونه")]
[assembly: AssemblyCopyright("Copyright © 2024 شرکت نمونه")]
[assembly: AssemblyTrademark("علامت تجاری نمونه")]
[assembly: AssemblyCulture("")]

// اطلاعات نسخه
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0-beta")]

// تنظیمات COM
[assembly: ComVisible(false)]
[assembly: Guid("12345678-1234-1234-1234-123456789012")]

// تنظیمات امنیتی و CLR
[assembly: System.CLSCompliant(true)]

// Metadata اضافی
[assembly: AssemblyMetadata("Author", "احمد محمدی")]
[assembly: AssemblyMetadata("BuildMachine", "BUILD-SERVER-01")]
[assembly: AssemblyMetadata("BuildDate", "2024-01-15")]

public class AssemblyAttributesExample
{
    public static void Main(string[] args)
    {
        Console.WriteLine("=== Assembly Attributes Examples ===");
        
        DisplayAssemblyInfo();
        DisplayCustomMetadata();
        DisplayVersionInfo();
    }
    
    private static void DisplayAssemblyInfo()
    {
        Console.WriteLine("\n--- Assembly Information ---");
        
        Assembly assembly = Assembly.GetExecutingAssembly();
        
        // دریافت اطلاعات کلی
        var titleAttr = assembly.GetCustomAttribute<AssemblyTitleAttribute>();
        var descAttr = assembly.GetCustomAttribute<AssemblyDescriptionAttribute>();
        var companyAttr = assembly.GetCustomAttribute<AssemblyCompanyAttribute>();
        var productAttr = assembly.GetCustomAttribute<AssemblyProductAttribute>();
        var copyrightAttr = assembly.GetCustomAttribute<AssemblyCopyrightAttribute>();
        
        Console.WriteLine($"Title: {titleAttr?.Title ?? "N/A"}");
        Console.WriteLine($"Description: {descAttr?.Description ?? "N/A"}");
        Console.WriteLine($"Company: {companyAttr?.Company ?? "N/A"}");
        Console.WriteLine($"Product: {productAttr?.Product ?? "N/A"}");
        Console.WriteLine($"Copyright: {copyrightAttr?.Copyright ?? "N/A"}");
        
        // اطلاعات فایل
        Console.WriteLine($"Location: {assembly.Location}");
        Console.WriteLine($"Full Name: {assembly.FullName}");
    }
    
    private static void DisplayCustomMetadata()
    {
        Console.WriteLine("\n--- Custom Metadata ---");
        
        Assembly assembly = Assembly.GetExecutingAssembly();
        
        // دریافت تمام AssemblyMetadata attributes
        var metadataAttrs = assembly.GetCustomAttributes<AssemblyMetadataAttribute>();
        
        foreach (var attr in metadataAttrs)
        {
            Console.WriteLine($"{attr.Key}: {attr.Value}");
        }
    }
    
    private static void DisplayVersionInfo()
    {
        Console.WriteLine("\n--- Version Information ---");
        
        Assembly assembly = Assembly.GetExecutingAssembly();
        
        // AssemblyVersion
        Version assemblyVersion = assembly.GetName().Version;
        Console.WriteLine($"Assembly Version: {assemblyVersion}");
        
        // AssemblyFileVersion
        var fileVersionAttr = assembly.GetCustomAttribute<AssemblyFileVersionAttribute>();
        Console.WriteLine($"File Version: {fileVersionAttr?.Version ?? "N/A"}");
        
        // AssemblyInformationalVersion
        var infoVersionAttr = assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
        Console.WriteLine($"Informational Version: {infoVersionAttr?.InformationalVersion ?? "N/A"}");
        
        // تاریخ ساخت (تقریبی از PE header)
        DateTime buildDate = GetBuildDate(assembly);
        Console.WriteLine($"Build Date (estimated): {buildDate}");
    }
    
    private static DateTime GetBuildDate(Assembly assembly)
    {
        // روش تقریبی برای دریافت تاریخ build
        var version = assembly.GetName().Version;
        if (version != null)
        {
            // استفاده از Build number به عنوان روزهای گذشته از 2000/1/1
            var baseDate = new DateTime(2000, 1, 1);
            return baseDate.AddDays(version.Build).AddSeconds(version.Revision * 2);
        }
        
        return DateTime.MinValue;
    }
}

// کلاس نمونه برای نمایش استفاده از Assembly attributes در کد
public static class AssemblyHelper
{
    public static string GetApplicationTitle()
    {
        var assembly = Assembly.GetExecutingAssembly();
        var titleAttr = assembly.GetCustomAttribute<AssemblyTitleAttribute>();
        return titleAttr?.Title ?? "Unknown Application";
    }
    
    public static string GetApplicationVersion()
    {
        var assembly = Assembly.GetExecutingAssembly();
        var version = assembly.GetName().Version;
        return version?.ToString() ?? "Unknown Version";
    }
    
    public static string GetCopyright()
    {
        var assembly = Assembly.GetExecutingAssembly();
        var copyrightAttr = assembly.GetCustomAttribute<AssemblyCopyrightAttribute>();
        return copyrightAttr?.Copyright ?? "No Copyright Information";
    }
    
    public static void ShowAboutDialog()
    {
        Console.WriteLine("=== About This Application ===");
        Console.WriteLine($"Title: {GetApplicationTitle()}");
        Console.WriteLine($"Version: {GetApplicationVersion()}");
        Console.WriteLine($"Copyright: {GetCopyright()}");
        Console.WriteLine("===============================");
    }
}

۱۰۰. Generic Math در C# چیست؟

پاسخ:

Generic Math قابلیتی در .NET 7 / C# 11 است که به شما اجازه می‌دهد تا متدهای جنریک بنویسید که می‌توانند عملیات ریاضی را بر روی انواع عددی مختلف انجام دهند. این کار با استفاده از اینترفیس‌های استاتیک انتزاعی (static abstract interfaces) امکان‌پذیر شده است و کاهش تکرار کد و افزایش قابلیت استفاده مجدد را فراهم می‌کند.

مزایای Generic Math:
مثال Generic Math:
using System;
using System.Collections.Generic;
using System.Numerics;

public class GenericMathExample
{
    // متد جنریک برای جمع دو عدد از هر نوع عددی
    public static T Add<T>(T left, T right)
        where T : IAdditionOperators<T, T, T>
    {
        return left + right;
    }

    // متد جنریک برای محاسبه میانگین
    public static T Average<T>(IEnumerable<T> numbers)
        where T : INumber<T>
    {
        T sum = T.Zero;
        int count = 0;
        foreach (T number in numbers)
        {
            sum += number;
            count++;
        }
        return sum / T.CreateChecked(count);
    }

    // متد جنریک برای محاسبه قدر مطلق
    public static T Abs<T>(T value)
        where T : INumber<T>
    {
        return T.Abs(value);
    }

    // متد جنریک برای پیدا کردن حداکثر
    public static T Max<T>(T left, T right)
        where T : IComparisonOperators<T, T, bool>
    {
        return left > right ? left : right;
    }

    // متد جنریک برای محاسبه توان
    public static T Power<T>(T baseValue, int exponent)
        where T : INumber<T>
    {
        if (exponent == 0) return T.One;
        if (exponent == 1) return baseValue;
        
        T result = T.One;
        T currentBase = baseValue;
        int currentExponent = exponent;
        
        if (currentExponent < 0)
        {
            currentExponent = -currentExponent;
            // برای اعداد منفی، باید تقسیم کنیم (فقط برای floating point)
        }
        
        while (currentExponent > 0)
        {
            if (currentExponent % 2 == 1)
            {
                result *= currentBase;
            }
            currentBase *= currentBase;
            currentExponent /= 2;
        }
        
        return result;
    }

    // کلاس Calculator جنریک
    public static class Calculator<T> where T : INumber<T>
    {
        public static T Add(T a, T b) => a + b;
        public static T Subtract(T a, T b) => a - b;
        public static T Multiply(T a, T b) => a * b;
        public static T Divide(T a, T b) => a / b;
        
        public static T Sum(params T[] values)
        {
            T result = T.Zero;
            foreach (T value in values)
            {
                result += value;
            }
            return result;
        }
        
        public static bool IsPositive(T value) => value > T.Zero;
        public static bool IsNegative(T value) => value < T.Zero;
        public static bool IsZero(T value) => value == T.Zero;
    }

    public static void Main(string[] args)
    {
        Console.WriteLine("=== Generic Math Examples ===");
        
        // استفاده با انواع مختلف عددی
        Console.WriteLine("\n--- Basic Operations ---");
        
        // int
        Console.WriteLine($"Add ints: {Add(5, 10)}"); // 15
        Console.WriteLine($"Add doubles: {Add(5.5, 10.2)}"); // 15.7
        Console.WriteLine($"Add decimals: {Add(5.5m, 10.2m)}"); // 15.7
        
        // محاسبه میانگین
        Console.WriteLine("\n--- Average Calculations ---");
        
        List<int> intNumbers = new List<int> { 1, 2, 3, 4, 5 };
        Console.WriteLine($"Average of ints: {Average(intNumbers)}"); // 3
        
        List<double> doubleNumbers = new List<double> { 1.0, 2.5, 3.5, 4.0 };
        Console.WriteLine($"Average of doubles: {Average(doubleNumbers)}"); // 2.75
        
        List<decimal> decimalNumbers = new List<decimal> { 10m, 20m, 30m };
        Console.WriteLine($"Average of decimals: {Average(decimalNumbers)}"); // 20
        
        // قدر مطلق
        Console.WriteLine("\n--- Absolute Values ---");
        Console.WriteLine($"Abs(-5): {Abs(-5)}"); // 5
        Console.WriteLine($"Abs(-3.14): {Abs(-3.14)}"); // 3.14
        Console.WriteLine($"Abs(-2.5m): {Abs(-2.5m)}"); // 2.5
        
        // حداکثر
        Console.WriteLine("\n--- Maximum Values ---");
        Console.WriteLine($"Max(10, 20): {Max(10, 20)}"); // 20
        Console.WriteLine($"Max(3.14, 2.71): {Max(3.14, 2.71)}"); // 3.14
        
        // توان
        Console.WriteLine("\n--- Power Calculations ---");
        Console.WriteLine($"Power(2, 3): {Power(2, 3)}"); // 8
        Console.WriteLine($"Power(1.5, 2): {Power(1.5, 2)}"); // 2.25
        
        // استفاده از Calculator جنریک
        Console.WriteLine("\n--- Generic Calculator ---");
        
        Console.WriteLine($"Calculator<int>.Add(15, 25): {Calculator<int>.Add(15, 25)}");
        Console.WriteLine($"Calculator<double>.Multiply(2.5, 4.0): {Calculator<double>.Multiply(2.5, 4.0)}");
        Console.WriteLine($"Calculator<decimal>.Sum(1m, 2m, 3m, 4m): {Calculator<decimal>.Sum(1m, 2m, 3m, 4m)}");
        
        // بررسی علامت
        Console.WriteLine($"Calculator<int>.IsPositive(5): {Calculator<int>.IsPositive(5)}");
        Console.WriteLine($"Calculator<double>.IsNegative(-2.5): {Calculator<double>.IsNegative(-2.5)}");
        Console.WriteLine($"Calculator<decimal>.IsZero(0m): {Calculator<decimal>.IsZero(0m)}");
        
        // مثال پیشرفته: محاسبه انحراف معیار
        Console.WriteLine("\n--- Advanced Example: Standard Deviation ---");
        
        List<double> data = new List<double> { 2, 4, 4, 4, 5, 5, 7, 9 };
        double stdDev = CalculateStandardDeviation(data);
        Console.WriteLine($"Standard deviation: {stdDev:F2}");
    }
    
    // مثال پیشرفته: محاسبه انحراف معیار
    public static T CalculateStandardDeviation<T>(IEnumerable<T> values)
        where T : IFloatingPoint<T>
    {
        var valuesList = values.ToList();
        if (valuesList.Count == 0) return T.Zero;
        
        T mean = Average(valuesList);
        T sumOfSquares = T.Zero;
        
        foreach (T value in valuesList)
        {
            T diff = value - mean;
            sumOfSquares += diff * diff;
        }
        
        T variance = sumOfSquares / T.CreateChecked(valuesList.Count);
        return T.Sqrt(variance);
    }
}
نکات پایانی:

🎉 تبریک! شما تمام ۱۰۰ سوال C# را مطالعه کردید!

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

موفق باشید! 🚀