← بازگشت

سوالات مصاحبه .NET Core و .NET Framework

سوالات پایه .NET Core و .NET Framework

1. .NET Core چیست و چه تفاوتی با .NET Framework دارد؟

پاسخ:

.NET Core (که اکنون به سادگی .NET نامیده می‌شود) و .NET Framework هر دو پلتفرم‌های توسعه نرم‌افزار از مایکروسافت هستند که برای ساخت انواع مختلفی از برنامه‌ها استفاده می‌شوند.

تفاوت‌های کلیدی:
نتیجه‌گیری: برای پروژه‌های جدید، همیشه .NET Core توصیه می‌شود زیرا از مزایای عملکردی، کراس‌پلتفرم بودن و اکوسیستم مدرن بهره‌مند است.

2. Common Language Runtime (CLR) در .NET Core چیست و چرا مهم است؟

پاسخ:

Common Language Runtime (CLR) جزء اصلی پلتفرم .NET است که مسئول مدیریت و اجرای کد .NET است.

وظایف اصلی CLR:
اهمیت: CLR یک لایه انتزاعی بین کد .NET و سخت‌افزار فراهم می‌کند که امکان اجرای برنامه‌ها روی پلتفرم‌های مختلف را بدون تغییر فراهم می‌کند.

3. هدف از دستور `dotnet new` چیست؟

پاسخ:

دستور dotnet new بخشی از .NET CLI است و برای ایجاد پروژه‌های جدید، فایل‌ها یا راه‌حل‌ها بر اساس الگوهای از پیش تعریف شده استفاده می‌شود.

مثال‌های کاربردی:
dotnet new console -o MyConsoleApp
dotnet new webapi -o MyWebApi
dotnet new sln -n MySolution
dotnet new list
مزیت: این دستور در محیط‌های CI/CD و اسکریپت‌نویسی بسیار مفید است.

4. .NET Core چگونه از توسعه کراس‌پلتفرم پشتیبانی می‌کند؟

پاسخ:

.NET Core از ابتدا با هدف پشتیبانی از توسعه کراس‌پلتفرم طراحی شده است.

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

5. Kestrel چیست و چرا در .NET Core استفاده می‌شود؟

پاسخ:

Kestrel یک وب سرور کراس‌پلتفرم، سبک و بسیار سریع است که به طور پیش‌فرض در پروژه‌های ASP.NET Core استفاده می‌شود.

مزایای Kestrel:
توصیه تولید: در محیط‌های تولیدی، Kestrel را پشت یک Reverse Proxy مانند IIS، Nginx یا Apache قرار دهید برای Load Balancing، SSL Termination و Security Hardening.

6. Middleware در ASP.NET Core چیست؟

پاسخ:

Middleware کامپوننت‌های نرم‌افزاری هستند که در خط لوله پردازش درخواست قرار می‌گیرند و می‌توانند درخواست‌های HTTP و پاسخ‌ها را بررسی، مسیریابی یا اصلاح کنند.

کاربردهای Middleware:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

app.Run();
نکته مهم: ترتیب Middlewareها در خط لوله بسیار مهم است.

7. تفاوت بین `dotnet run` و `dotnet build` چیست؟

پاسخ:

هر دو دستور بخشی از .NET CLI هستند اما هدف متفاوتی دارند:

dotnet build:
dotnet run:
کاربرد: توسعه‌دهندگان معمولاً از dotnet run در طول توسعه و از dotnet build در CI/CD استفاده می‌کنند.

8. `appsettings.json` چیست و چگونه تنظیمات را در آن پیکربندی می‌کنید؟

پاسخ:

appsettings.json فایل پیکربندی در پروژه‌های ASP.NET Core است که برای ذخیره تنظیمات برنامه استفاده می‌شود.

مثال appsettings.json:
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=.;Database=MyDB;Trusted_Connection=True;"
  },
  "ApiKey": "MySecretApiKey"
}
دسترسی به تنظیمات:
public class MyController : ControllerBase
{
    private readonly IConfiguration _configuration;

    public MyController(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    [HttpGet]
    public IActionResult GetApiKey()
    {
        string apiKey = _configuration["ApiKey"];
        string connectionString = _configuration.GetConnectionString("DefaultConnection");
        return Ok(new { ApiKey = apiKey });
    }
}
Options Pattern: برای دسترسی نوع‌امن، از Options Pattern و کلاس‌های POCO استفاده کنید.

9. تفاوت بین `IActionResult` و `ActionResult` در یک کنترلر ASP.NET Core چیست؟

پاسخ:

هر دو به عنوان نوع بازگشتی برای متدهای اکشن در کنترلرهای ASP.NET Core استفاده می‌شوند:

IActionResult:
public IActionResult GetUser(int id)
{
    if (id <= 0)
        return BadRequest("Invalid ID");
    
    var user = GetUserById(id);
    if (user == null)
        return NotFound();
    
    return Ok(user);
}
ActionResult<T>:
public ActionResult<User> GetUser(int id)
{
    if (id <= 0)
        return BadRequest("Invalid ID");
    
    var user = GetUserById(id);
    if (user == null)
        return NotFound();
    
    return user; // بازگشت مستقیم نوع User
}
توصیه: برای Web APIها از ActionResult<T> استفاده کنید.

10. Service Lifetime در Dependency Injection چیست؟

پاسخ:

Service Lifetime تعیین می‌کند که چگونه و چه زمانی نمونه‌های سرویس‌ها در Dependency Injection ایجاد و مدیریت می‌شوند.

سه نوع Lifetime:
// در Program.cs
builder.Services.AddSingleton<ISingletonService, SingletonService>();
builder.Services.AddScoped<IScopedService, ScopedService>();
builder.Services.AddTransient<ITransientService, TransientService>();
انتخاب مناسب:
  • Singleton: برای سرویس‌های بدون وضعیت و thread-safe
  • Scoped: برای DbContext و سرویس‌های مرتبط با درخواست
  • Transient: برای سرویس‌های سبک و بدون وضعیت

11. Repository Pattern چیست و چرا استفاده می‌شود؟

پاسخ:

Repository Pattern یک الگوی طراحی است که لایه‌ای از انتزاع بین منطق کسب‌وکار و لایه دسترسی به داده ایجاد می‌کند.

مزایای Repository Pattern:
public interface IUserRepository
{
    Task<User> GetByIdAsync(int id);
    Task<IEnumerable<User>> GetAllAsync();
    Task AddAsync(User user);
    Task UpdateAsync(User user);
    Task DeleteAsync(int id);
}

public class UserRepository : IUserRepository
{
    private readonly ApplicationDbContext _context;
    
    public UserRepository(ApplicationDbContext context)
    {
        _context = context;
    }
    
    public async Task<User> GetByIdAsync(int id)
    {
        return await _context.Users.FindAsync(id);
    }
}
نکته: در Entity Framework Core مدرن، DbContext خود به عنوان Repository عمل می‌کند و نیاز به پیاده‌سازی جداگانه کمتر است.

12. Entity Framework Core چیست و چه مزایایی دارد؟

پاسخ:

Entity Framework Core یک ORM (Object-Relational Mapping) مدرن و سبک برای .NET است که دسترسی به پایگاه داده را ساده‌تر می‌کند.

مزایای EF Core:
// تعریف DbContext
public class ApplicationDbContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Product> Products { get; set; }
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(connectionString);
    }
}

// استفاده از LINQ
var activeUsers = await _context.Users
    .Where(u => u.IsActive)
    .OrderBy(u => u.Name)
    .ToListAsync();
Code First vs Database First: EF Core هر دو رویکرد را پشتیبانی می‌کند، اما Code First رایج‌تر است.

13. LINQ چیست و چه کاربردهایی دارد؟

پاسخ:

LINQ (Language Integrated Query) یک فناوری در .NET است که امکان نوشتن کوئری‌های یکپارچه روی انواع مختلف منابع داده را فراهم می‌کند.

انواع LINQ:
// Query Syntax
var result = from user in users
             where user.Age > 18
             orderby user.Name
             select new { user.Name, user.Email };

// Method Syntax
var result = users
    .Where(u => u.Age > 18)
    .OrderBy(u => u.Name)
    .Select(u => new { u.Name, u.Email });

// عملیات‌های رایج
var count = users.Count(u => u.IsActive);
var firstUser = users.FirstOrDefault(u => u.Id == 1);
var groupedUsers = users.GroupBy(u => u.Department);
مزیت: LINQ کد را خواناتر، کوتاه‌تر و کمتر مستعد خطا می‌کند و از IntelliSense و Type Safety بهره‌مند است.

14. Lambda Expression چیست و چگونه استفاده می‌شود؟

پاسخ:

Lambda Expression راهی مختصر برای نوشتن توابع ناشناس (Anonymous Functions) در C# است که بیشتر با LINQ و Delegates استفاده می‌شود.

ساختار Lambda:
// ساختار کلی: (parameters) => expression یا statement

// Lambda ساده
x => x * 2

// Lambda با چند پارامتر
(x, y) => x + y

// Lambda با بدنه
x => {
    Console.WriteLine($"Processing: {x}");
    return x * 2;
}
کاربردهای عملی:
// با LINQ
var evenNumbers = numbers.Where(n => n % 2 == 0);
var doubled = numbers.Select(n => n * 2);

// با Delegates
Action<string> print = message => Console.WriteLine(message);
Func<int, int, int> add = (a, b) => a + b;

// Event Handling
button.Click += (sender, e) => MessageBox.Show("Clicked!");

// Async Lambda
var result = await Task.Run(() => SomeHeavyOperation());
مزایا: کد مختصرتر، خوانایی بهتر، و امکان استفاده از متغیرهای محلی (Closure).

15. async/await چیست و چگونه کار می‌کند؟

پاسخ:

async/await الگویی در C# برای نوشتن کد ناهمزمان (Asynchronous) است که به شکل همزمان نوشته می‌شود.

مفاهیم کلیدی:
// متد async
public async Task<string> GetDataAsync()
{
    using var httpClient = new HttpClient();
    var response = await httpClient.GetStringAsync("https://api.example.com/data");
    return response;
}

// استفاده از async/await
public async Task ProcessDataAsync()
{
    try
    {
        var data = await GetDataAsync();
        Console.WriteLine($"Received: {data}");
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
    }
}
مثال عملی در ASP.NET Core:
[HttpGet]
public async Task<ActionResult<List<User>>> GetUsersAsync()
{
    var users = await _userService.GetAllUsersAsync();
    return Ok(users);
}
مزایا: بهبود عملکرد و پاسخگویی برنامه، استفاده بهتر از منابع سیستم، و جلوگیری از مسدود شدن UI.

16. Task و Thread چه تفاوتی دارند؟

پاسخ:

Task و Thread هر دو برای اجرای کد به صورت موازی استفاده می‌شوند، اما تفاوت‌های مهمی دارند:

Thread:
// استفاده از Thread
var thread = new Thread(() => {
    Console.WriteLine("Running on thread");
});
thread.Start();
thread.Join();
Task:
// استفاده از Task
var task = Task.Run(() => {
    Console.WriteLine("Running on task");
});
await task;

// Task با نتیجه
var result = await Task.Run(() => {
    return SomeCalculation();
});
توصیه: در .NET مدرن، همیشه از Task به جای Thread استفاده کنید مگر در موارد خاص.

17. Garbage Collection در .NET چگونه کار می‌کند؟

پاسخ:

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

نسل‌های GC:
مراحل GC:
// کنترل دستی GC (توصیه نمی‌شود)
GC.Collect();
GC.WaitForPendingFinalizers();

// بررسی وضعیت حافظه
var gen0 = GC.CollectionCount(0);
var totalMemory = GC.GetTotalMemory(false);

// استفاده از using برای مدیریت منابع
using (var fileStream = new FileStream("file.txt", FileMode.Open))
{
    // کار با فایل
} // خودکار Dispose می‌شود
بهترین روش‌ها: از using برای منابع استفاده کنید، از ایجاد اشیاء غیرضروری خودداری کنید، و GC را دستی فراخوانی نکنید.

18. IDisposable چیست و چه زمانی استفاده می‌شود؟

پاسخ:

IDisposable اینترفیسی است که برای آزادسازی منابع غیرمدیریت شده (Unmanaged Resources) مانند فایل‌ها، اتصالات پایگاه داده، و Socket ها استفاده می‌شود.

پیاده‌سازی IDisposable:
public class DatabaseConnection : IDisposable
{
    private SqlConnection _connection;
    private bool _disposed = false;

    public DatabaseConnection(string connectionString)
    {
        _connection = new SqlConnection(connectionString);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // آزادسازی منابع مدیریت شده
                _connection?.Dispose();
            }
            
            // آزادسازی منابع غیرمدیریت شده
            _disposed = true;
        }
    }

    ~DatabaseConnection()
    {
        Dispose(false);
    }
}
استفاده با using:
// using statement
using (var connection = new DatabaseConnection(connectionString))
{
    // کار با اتصال
} // خودکار Dispose می‌شود

// using declaration (C# 8+)
using var connection = new DatabaseConnection(connectionString);
// کار با اتصال
// در پایان scope خودکار Dispose می‌شود
کاربردها: فایل‌ها، اتصالات شبکه، DbConnection، HttpClient، و هر منبعی که نیاز به آزادسازی دستی دارد.

19. Configuration در ASP.NET Core چگونه کار می‌کند؟

پاسخ:

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

منابع Configuration (به ترتیب اولویت):
// در Program.cs
var builder = WebApplication.CreateBuilder(args);

// اضافه کردن منابع Configuration
builder.Configuration
    .AddJsonFile("appsettings.json", optional: false)
    .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)
    .AddEnvironmentVariables()
    .AddCommandLine(args);

var app = builder.Build();
خواندن تنظیمات:
// دسترسی مستقیم
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
var apiKey = builder.Configuration["ApiSettings:Key"];

// Options Pattern
public class ApiSettings
{
    public string Key { get; set; }
    public string BaseUrl { get; set; }
}

builder.Services.Configure<ApiSettings>(
    builder.Configuration.GetSection("ApiSettings"));

// در کنترلر
public class HomeController : Controller
{
    private readonly ApiSettings _apiSettings;
    
    public HomeController(IOptions<ApiSettings> apiSettings)
    {
        _apiSettings = apiSettings.Value;
    }
}
امنیت: برای اطلاعات حساس از User Secrets در توسعه و Azure Key Vault در تولید استفاده کنید.

20. Logging در ASP.NET Core چگونه پیکربندی می‌شود؟

پاسخ:

Logging در ASP.NET Core یک سیستم انعطاف‌پذیر و قدرتمند برای ثبت رویدادها و خطاهای برنامه است.

سطوح Log:
// پیکربندی در appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.EntityFrameworkCore": "Information"
    }
  }
}
استفاده در کنترلر:
public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger;
    }

    public IActionResult Index()
    {
        _logger.LogInformation("Home page visited at {Time}", DateTime.Now);
        
        try
        {
            // کد اصلی
            return View();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error occurred in Home/Index");
            return View("Error");
        }
    }
}
اضافه کردن Provider های مختلف:
// در Program.cs
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddDebug();
builder.Logging.AddEventSourceLogger();

// Third-party providers
builder.Logging.AddSerilog();
builder.Logging.AddNLog();
بهترین روش‌ها: از Structured Logging استفاده کنید، سطح مناسب انتخاب کنید، و در تولید از providerهای خارجی مانند Serilog استفاده کنید.

21. تفاوت بین Authentication و Authorization چیست؟

پاسخ:

این دو مفهوم امنیتی اغلب با هم اشتباه گرفته می‌شوند، اما نقش‌های متفاوتی دارند:

Authentication (احراز هویت):
Authorization (مجوزدهی):
// در ASP.NET Core

// Authentication
app.UseAuthentication(); // بررسی توکن یا کوکی

// Authorization
app.UseAuthorization(); // بررسی نقش‌ها و سیاست‌ها

[Authorize] // نیاز به احراز هویت
public class SecureController : ControllerBase { }

[Authorize(Roles = "Admin")] // نیاز به نقش ادمین
public class AdminController : ControllerBase { }

[Authorize(Policy = "CanEditProducts")] // نیاز به سیاست خاص
public class ProductController : ControllerBase { }
نکته کلیدی: Authentication همیشه قبل از Authorization انجام می‌شود.

22. JWT چیست و چگونه در ASP.NET Core استفاده می‌شود؟

پاسخ:

JWT (JSON Web Token) یک استاندارد باز برای ایجاد توکن‌های دسترسی است که اطلاعات را به صورت JSON بین دو طرف منتقل می‌کند.

ساختار JWT:
// پیکربندی JWT در Program.cs
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };
    });

// ایجاد توکن
var claims = new[]
{
    new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
    new Claim(ClaimTypes.Role, "Admin")
};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(
    issuer: _config["Jwt:Issuer"],
    audience: _config["Jwt:Audience"],
    claims: claims,
    expires: DateTime.Now.AddMinutes(30),
    signingCredentials: creds
);

var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
مزایا: Stateless، قابل حمل، و مناسب برای میکروسرویس‌ها و APIها.

23. CORS چیست و چگونه در ASP.NET Core فعال می‌شود؟

پاسخ:

CORS (Cross-Origin Resource Sharing) مکانیزمی است که به یک برنامه وب اجازه می‌دهد تا از منابع یک دامنه دیگر درخواست کند.

پیکربندی CORS:
// در Program.cs

var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
                      policy =>
                      {
                          policy.WithOrigins("https://www.example.com",
                                              "https://app.example.com")
                                .WithMethods("GET", "POST", "PUT")
                                .WithHeaders("Content-Type", "Authorization");
                      });
});

var app = builder.Build();

app.UseCors(MyAllowSpecificOrigins);

app.Run();
فعال‌سازی با Attribute:
[EnableCors("_myAllowSpecificOrigins")]
[ApiController]
[Route("[controller]")]
public class MyController : ControllerBase { }

[DisableCors]
public class AnotherController : ControllerBase { }
امنیت: همیشه دامنه‌های مجاز را مشخص کنید و از AllowAnyOrigin() در تولید خودداری کنید.

24. Health Checks در ASP.NET Core چیست؟

پاسخ:

Health Checks یک ویژگی در ASP.NET Core است که یک endpoint برای گزارش وضعیت سلامت برنامه فراهم می‌کند.

کاربردها:
// در Program.cs
builder.Services.AddHealthChecks()
    .AddDbContextCheck<ApplicationDbContext>("Database")
    .AddUrlGroup(new Uri("https://api.example.com/status"), "External API");

var app = builder.Build();

app.MapHealthChecks("/health");

app.Run();
نتیجه: با مراجعه به /health، وضعیت سلامت برنامه و وابستگی‌های آن (مانند پایگاه داده) نمایش داده می‌شود.

25. Minimal APIs چیست و چه تفاوتی با کنترلرها دارد؟

پاسخ:

Minimal APIs یک رویکرد جدید در .NET 6+ برای ساخت APIهای سبک و سریع با کد کمتر است.

تفاوت‌های کلیدی:
// Minimal API در Program.cs
var app = WebApplication.Create();

app.MapGet("/", () => "Hello World!");

app.MapGet("/users/{id}", (int id, IUserService userService) => 
{
    var user = userService.GetById(id);
    return user is not null ? Results.Ok(user) : Results.NotFound();
});

app.Run();
انتخاب: برای APIهای بزرگ و پیچیده، کنترلرها هنوز گزینه بهتری هستند. برای APIهای کوچک و میکروسرویس‌ها، Minimal APIs عالی است.

26. تفاوت IQueryable و IEnumerable چیست؟

پاسخ:

هر دو برای کار با کالکشن‌ها استفاده می‌شوند، اما نحوه اجرای کوئری‌ها متفاوت است:

IEnumerable:
// تمام کاربران به حافظه منتقل می‌شوند
IEnumerable<User> users = _context.Users.ToList();

// فیلتر در حافظه انجام می‌شود
var activeUsers = users.Where(u => u.IsActive);
IQueryable:
// کوئری ساخته می‌شود اما اجرا نمی‌شود
IQueryable<User> users = _context.Users;

// فیلتر به کوئری SQL اضافه می‌شود
var activeUsersQuery = users.Where(u => u.IsActive);

// کوئری در پایگاه داده اجرا می‌شود
var result = activeUsersQuery.ToList();
توصیه: همیشه از IQueryable برای کار با Entity Framework استفاده کنید تا از مشکلات عملکردی جلوگیری شود.

27. Boxing و Unboxing چیست؟

پاسخ:

این دو مفهوم به تبدیل بین Value Types (مانند int, struct) و Reference Types (مانند object) اشاره دارند.

Boxing:
int i = 123;
object o = i; // Boxing
Unboxing:
object o = 123;
int i = (int)o; // Unboxing
بهترین روش: از Generics استفاده کنید تا از Boxing و Unboxing غیرضروری جلوگیری کنید.

28. تفاوت Struct و Class چیست؟

پاسخ:

این دو ساختار اصلی برای تعریف انواع داده در C# هستند:

Struct:
public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}
Class:
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
چه زمانی از Struct استفاده کنیم؟ زمانی که نوع شما کوچک است، تغییرناپذیر است، و رفتار یک نوع اولیه را دارد (مانند int).

29. SOLID Principles چیست؟

پاسخ:

SOLID مجموعه‌ای از پنج اصل طراحی شیءگرا است که به توسعه‌دهندگان کمک می‌کند تا نرم‌افزاری قابل فهم، انعطاف‌پذیر و قابل نگهداری بسازند.

اصول SOLID:
مزایا: کد تمیزتر، کاهش وابستگی‌ها، افزایش تست‌پذیری، و نگهداری آسان‌تر.

30. Unit Test چیست و چرا مهم است؟

پاسخ:

Unit Test نوعی تست نرم‌افزار است که کوچکترین بخش‌های قابل تست یک برنامه (واحدها یا Unit ها) را به صورت جداگانه و مستقل آزمایش می‌کند.

مزایای Unit Test:
// فریم‌ورک‌های تست در .NET
// xUnit, NUnit, MSTest

// مثال با xUnit و Moq
public class CalculatorTests
{
    [Fact]
    public void Add_TwoNumbers_ReturnsSum()
    {
        // Arrange
        var calculator = new Calculator();
        
        // Act
        var result = calculator.Add(2, 3);
        
        // Assert
        Assert.Equal(5, result);
    }
}

// Mock کردن وابستگی‌ها
[Fact]
public void GetUser_WithValidId_ReturnsUser()
{
    // Arrange
    var mockRepo = new Mock<IUserRepository>();
    mockRepo.Setup(repo => repo.GetById(1)).Returns(new User { Id = 1, Name = "Test" });
    var service = new UserService(mockRepo.Object);
    
    // Act
    var result = service.GetUser(1);
    
    // Assert
    Assert.NotNull(result);
    Assert.Equal(1, result.Id);
}
AAA Pattern: Arrange, Act, Assert یک الگوی رایج برای نوشتن Unit Test است.

31. Entity Framework Core Migration چیست؟

پاسخ:

Migration در Entity Framework Core روشی برای مدیریت تغییرات ساختار پایگاه داده به صورت کنترل شده و قابل ردیابی است.

دستورات Migration:
// ایجاد Migration جدید
dotnet ef migrations add InitialCreate

// اعمال Migration به پایگاه داده
dotnet ef database update

// حذف آخرین Migration
dotnet ef migrations remove

// مشاهده لیست Migration ها
dotnet ef migrations list
مثال Migration:
public partial class AddUserTable : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Users",
            columns: table => new
            {
                Id = table.Column<int>(type: "int", nullable: false)
                    .Annotation("SqlServer:Identity", "1, 1"),
                Name = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
                Email = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Users", x => x.Id);
            });
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(name: "Users");
    }
}
مزایا: کنترل نسخه ساختار پایگاه داده، امکان rollback، و همگام‌سازی تیم توسعه.

32. Code First و Database First چه تفاوتی دارند؟

پاسخ:

دو رویکرد مختلف برای کار با Entity Framework Core:

Code First:
// تعریف مدل
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public List<Order> Orders { get; set; }
}

// DbContext
public class ApplicationDbContext : DbContext
{
    public DbSet<User> Users { get; set; }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .Property(u => u.Name)
            .HasMaxLength(100)
            .IsRequired();
    }
}
Database First:
// تولید مدل از پایگاه داده
dotnet ef dbcontext scaffold "Server=.;Database=MyDB;Trusted_Connection=true;" Microsoft.EntityFrameworkCore.SqlServer -o Models
توصیه: برای پروژه‌های جدید از Code First استفاده کنید.

33. Lazy Loading در Entity Framework چیست؟

پاسخ:

Lazy Loading یک الگو در Entity Framework است که داده‌های مرتبط را تنها زمانی بارگذاری می‌کند که به آن‌ها دسترسی پیدا شود.

فعال‌سازی Lazy Loading:
// نصب پکیج
// Microsoft.EntityFrameworkCore.Proxies

// فعال‌سازی در DbContext
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseLazyLoadingProxies()
                  .UseSqlServer(connectionString);
}

// تعریف Navigation Properties به صورت virtual
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual List<Order> Orders { get; set; } // virtual برای Lazy Loading
}
مقایسه با Eager Loading:
// Lazy Loading - داده‌ها در زمان دسترسی بارگذاری می‌شوند
var user = context.Users.First();
var orders = user.Orders; // در اینجا کوئری اجرا می‌شود

// Eager Loading - داده‌ها از ابتدا بارگذاری می‌شوند
var userWithOrders = context.Users
    .Include(u => u.Orders)
    .First();
مزایا و معایب: کد ساده‌تر اما احتمال N+1 Query Problem و مشکل در محیط‌های غیرمتصل.

34. Performance Optimization در ASP.NET Core چگونه انجام می‌شود؟

پاسخ:

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

تکنیک‌های بهینه‌سازی:
// Response Caching
[ResponseCache(Duration = 300)] // 5 دقیقه
public IActionResult GetProducts()
{
    return Ok(products);
}

// Memory Caching
public class ProductService
{
    private readonly IMemoryCache _cache;
    
    public async Task<List<Product>> GetProductsAsync()
    {
        if (!_cache.TryGetValue("products", out List<Product> products))
        {
            products = await _repository.GetAllAsync();
            _cache.Set("products", products, TimeSpan.FromMinutes(10));
        }
        return products;
    }
}

// Response Compression در Program.cs
builder.Services.AddResponseCompression(options =>
{
    options.EnableForHttps = true;
    options.Providers.Add<GzipCompressionProvider>();
});

app.UseResponseCompression();
مانیتورینگ: از ابزارهایی مانند Application Insights و MiniProfiler برای اندازه‌گیری عملکرد استفاده کنید.

35. Caching در ASP.NET Core چگونه پیاده‌سازی می‌شود؟

پاسخ:

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

انواع Caching:
// In-Memory Caching
builder.Services.AddMemoryCache();

public class HomeController : Controller
{
    private readonly IMemoryCache _memoryCache;
    
    public HomeController(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;
    }
    
    public async Task<IActionResult> Index()
    {
        var cacheKey = "product-list";
        
        if (!_memoryCache.TryGetValue(cacheKey, out List<Product> products))
        {
            products = await _productService.GetAllAsync();
            
            var cacheOptions = new MemoryCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10),
                SlidingExpiration = TimeSpan.FromMinutes(2)
            };
            
            _memoryCache.Set(cacheKey, products, cacheOptions);
        }
        
        return View(products);
    }
}
Distributed Caching با Redis:
// در Program.cs
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "localhost:6379";
});

// استفاده
public class ProductService
{
    private readonly IDistributedCache _distributedCache;
    
    public async Task<List<Product>> GetProductsAsync()
    {
        var cacheKey = "products";
        var cachedProducts = await _distributedCache.GetStringAsync(cacheKey);
        
        if (cachedProducts != null)
        {
            return JsonSerializer.Deserialize<List<Product>>(cachedProducts);
        }
        
        var products = await _repository.GetAllAsync();
        var serializedProducts = JsonSerializer.Serialize(products);
        
        await _distributedCache.SetStringAsync(cacheKey, serializedProducts, new DistributedCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
        });
        
        return products;
    }
}
انتخاب نوع کش: برای برنامه‌های تک سرور از In-Memory، برای برنامه‌های چند سرور از Distributed Cache استفاده کنید.

36. SignalR چیست و چه کاربردی دارد؟

پاسخ:

SignalR یک کتابخانه برای ASP.NET Core است که امکان ارتباط دوطرفه و real-time بین سرور و کلاینت را فراهم می‌کند.

کاربردهای SignalR:
// تعریف Hub
public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
    
    public async Task JoinGroup(string groupName)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
        await Clients.Group(groupName).SendAsync("UserJoined", Context.User.Identity.Name);
    }
}

// پیکربندی در Program.cs
builder.Services.AddSignalR();

app.MapHub<ChatHub>("/chathub");
کلاینت JavaScript:
const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .build();

// دریافت پیام
connection.on("ReceiveMessage", function (user, message) {
    const msg = user + ": " + message;
    document.getElementById("messagesList").innerHTML += "<li>" + msg + "</li>";
});

// ارسال پیام
document.getElementById("sendButton").addEventListener("click", function (event) {
    const user = document.getElementById("userInput").value;
    const message = document.getElementById("messageInput").value;
    connection.invoke("SendMessage", user, message).catch(function (err) {
        console.error(err.toString());
    });
    event.preventDefault();
});

// شروع اتصال
connection.start();
پروتکل‌ها: SignalR از WebSockets، Server-Sent Events، و Long Polling پشتیبانی می‌کند و بهترین گزینه را خودکار انتخاب می‌کند.

37. Background Services در ASP.NET Core چیست؟

پاسخ:

Background Services امکان اجرای کارهای پس‌زمینه در ASP.NET Core را فراهم می‌کنند، مانند پردازش صف، ارسال ایمیل، یا کارهای دوره‌ای.

پیاده‌سازی Background Service:
public class EmailBackgroundService : BackgroundService
{
    private readonly ILogger<EmailBackgroundService> _logger;
    private readonly IServiceProvider _serviceProvider;

    public EmailBackgroundService(ILogger<EmailBackgroundService> logger, IServiceProvider serviceProvider)
    {
        _logger = logger;
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using (var scope = _serviceProvider.CreateScope())
            {
                var emailService = scope.ServiceProvider.GetRequiredService<IEmailService>();
                
                try
                {
                    await emailService.ProcessPendingEmailsAsync();
                    _logger.LogInformation("Email processing completed at: {time}", DateTimeOffset.Now);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error occurred executing email service");
                }
            }
            
            await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
        }
    }
}
ثبت در DI Container:
// در Program.cs
builder.Services.AddHostedService<EmailBackgroundService>();
نکات مهم: Background Services در thread جداگانه اجرا می‌شوند و نباید به DbContext مستقیماً دسترسی داشته باشند. از IServiceScope استفاده کنید.

38. API Versioning در ASP.NET Core چگونه پیاده‌سازی می‌شود؟

پاسخ:

API Versioning امکان نگهداری چندین نسخه از API به صورت همزمان را فراهم می‌کند تا سازگاری با کلاینت‌های قدیمی حفظ شود.

روش‌های Versioning:
// نصب پکیج
// Microsoft.AspNetCore.Mvc.Versioning

// پیکربندی در Program.cs
builder.Services.AddApiVersioning(opt =>
{
    opt.DefaultApiVersion = new ApiVersion(1, 0);
    opt.AssumeDefaultVersionWhenUnspecified = true;
    opt.ApiVersionReader = ApiVersionReader.Combine(
        new UrlSegmentApiVersionReader(),
        new QueryStringApiVersionReader("version"),
        new HeaderApiVersionReader("X-Version")
    );
});

builder.Services.AddVersionedApiExplorer(setup =>
{
    setup.GroupNameFormat = "'v'VVV";
    setup.SubstituteApiVersionInUrl = true;
});
استفاده در کنترلر:
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class UsersV1Controller : ControllerBase
{
    [HttpGet]
    public ActionResult<IEnumerable<UserV1>> Get()
    {
        return Ok(usersV1);
    }
}

[ApiController]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class UsersV2Controller : ControllerBase
{
    [HttpGet]
    public ActionResult<IEnumerable<UserV2>> Get()
    {
        return Ok(usersV2);
    }
}
بهترین روش: از URL Path versioning استفاده کنید زیرا واضح‌تر و کش‌پذیرتر است.

39. Rate Limiting در ASP.NET Core چیست؟

پاسخ:

Rate Limiting تکنیکی برای محدود کردن تعداد درخواست‌هایی است که یک کلاینت می‌تواند در بازه زمانی مشخص ارسال کند.

پیکربندی Rate Limiting (.NET 7+):
// در Program.cs
builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter("FixedPolicy", opt =>
    {
        opt.PermitLimit = 10;
        opt.Window = TimeSpan.FromMinutes(1);
        opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        opt.QueueLimit = 5;
    });
    
    options.AddSlidingWindowLimiter("SlidingPolicy", opt =>
    {
        opt.PermitLimit = 100;
        opt.Window = TimeSpan.FromMinutes(1);
        opt.SegmentsPerWindow = 6;
    });
});

var app = builder.Build();

app.UseRateLimiter();
استفاده در کنترلر:
[EnableRateLimiting("FixedPolicy")]
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public ActionResult<IEnumerable<Product>> Get()
    {
        return Ok(products);
    }
    
    [EnableRateLimiting("SlidingPolicy")]
    [HttpPost]
    public ActionResult<Product> Post(Product product)
    {
        // ایجاد محصول
        return CreatedAtAction(nameof(Get), new { id = product.Id }, product);
    }
}
مزایا: محافظت در برابر حملات DDoS، کنترل استفاده از منابع، و بهبود کیفیت سرویس برای همه کاربران.

40. Docker و Containerization در .NET چیست؟

پاسخ:

Docker پلتفرمی برای containerization است که امکان بسته‌بندی برنامه‌های .NET همراه با تمام وابستگی‌ها را فراهم می‌کند.

مزایای Containerization:
Dockerfile برای ASP.NET Core:
# استفاده از runtime image
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

# استفاده از SDK image برای build
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyApp/MyApp.csproj", "MyApp/"]
RUN dotnet restore "MyApp/MyApp.csproj"
COPY . .
WORKDIR "/src/MyApp"
RUN dotnet build "MyApp.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "MyApp.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]
دستورات Docker:
# ساخت image
docker build -t myapp .

# اجرای container
docker run -d -p 8080:80 --name myapp-container myapp

# مشاهده لاگ‌ها
docker logs myapp-container

# ورود به container
docker exec -it myapp-container /bin/bash
بهینه‌سازی: از multi-stage builds استفاده کنید تا اندازه image کاهش یابد و از .dockerignore برای حذف فایل‌های غیرضروری استفاده کنید.

41. Microservices Architecture چیست؟

پاسخ:

Microservices یک الگوی معماری است که برنامه را به مجموعه‌ای از سرویس‌های کوچک، مستقل و قابل استقرار جداگانه تقسیم می‌کند.

مزایای Microservices:
چالش‌های Microservices:
ابزارهای .NET: Ocelot برای API Gateway، MassTransit برای Message Bus، و Polly برای Resilience.

42. API Gateway چیست و چرا استفاده می‌شود؟

پاسخ:

API Gateway یک سرویس واسط است که به عنوان نقطه ورودی واحد برای تمام درخواست‌های کلاینت به میکروسرویس‌ها عمل می‌کند.

وظایف API Gateway:
پیاده‌سازی با Ocelot:
// نصب پکیج
// Ocelot

// ocelot.json
{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/users/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5001
        }
      ],
      "UpstreamPathTemplate": "/users/{everything}",
      "UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE" ]
    },
    {
      "DownstreamPathTemplate": "/api/products/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5002
        }
      ],
      "UpstreamPathTemplate": "/products/{everything}",
      "UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE" ]
    }
  ]
}

// Program.cs
builder.Configuration.AddJsonFile("ocelot.json");
builder.Services.AddOcelot();

var app = builder.Build();
await app.UseOcelot();
مزیت: ساده‌سازی کلاینت‌ها، امنیت متمرکز، و مدیریت آسان‌تر میکروسرویس‌ها.

43. Message Queue و Service Bus چیست؟

پاسخ:

Message Queue و Service Bus الگوهایی برای ارتباط ناهمزمان بین سرویس‌ها هستند که امکان decoupling و مقیاس‌پذیری را فراهم می‌کنند.

مزایای Message-based Communication:
پیاده‌سازی با MassTransit:
// تعریف پیام
public class OrderCreated
{
    public int OrderId { get; set; }
    public string CustomerEmail { get; set; }
    public decimal Amount { get; set; }
}

// Publisher
public class OrderService
{
    private readonly IPublishEndpoint _publishEndpoint;
    
    public OrderService(IPublishEndpoint publishEndpoint)
    {
        _publishEndpoint = publishEndpoint;
    }
    
    public async Task CreateOrderAsync(Order order)
    {
        // ذخیره سفارش
        await _repository.SaveAsync(order);
        
        // ارسال پیام
        await _publishEndpoint.Publish(new OrderCreated
        {
            OrderId = order.Id,
            CustomerEmail = order.CustomerEmail,
            Amount = order.Amount
        });
    }
}

// Consumer
public class EmailNotificationConsumer : IConsumer<OrderCreated>
{
    private readonly IEmailService _emailService;
    
    public EmailNotificationConsumer(IEmailService emailService)
    {
        _emailService = emailService;
    }
    
    public async Task Consume(ConsumeContext<OrderCreated> context)
    {
        await _emailService.SendOrderConfirmationAsync(
            context.Message.CustomerEmail,
            context.Message.OrderId
        );
    }
}
ابزارها: RabbitMQ، Azure Service Bus، Apache Kafka از محبوب‌ترین گزینه‌ها هستند.

44. Circuit Breaker Pattern چیست؟

پاسخ:

Circuit Breaker الگویی برای مدیریت خرابی‌های شبکه و سرویس‌های خارجی است که از cascade failure جلوگیری می‌کند.

حالت‌های Circuit Breaker:
پیاده‌سازی با Polly:
// نصب پکیج
// Polly

// پیکربندی Circuit Breaker
var circuitBreakerPolicy = Policy
    .Handle<HttpRequestException>()
    .CircuitBreakerAsync(
        handledEventsAllowedBeforeBreaking: 3,
        durationOfBreak: TimeSpan.FromSeconds(30),
        onBreak: (exception, duration) =>
        {
            Console.WriteLine($"Circuit breaker opened for {duration}");
        },
        onReset: () =>
        {
            Console.WriteLine("Circuit breaker reset");
        });

// استفاده
public class ExternalApiService
{
    private readonly HttpClient _httpClient;
    private readonly IAsyncPolicy _circuitBreakerPolicy;
    
    public ExternalApiService(HttpClient httpClient, IAsyncPolicy circuitBreakerPolicy)
    {
        _httpClient = httpClient;
        _circuitBreakerPolicy = circuitBreakerPolicy;
    }
    
    public async Task<string> GetDataAsync()
    {
        try
        {
            return await _circuitBreakerPolicy.ExecuteAsync(async () =>
            {
                var response = await _httpClient.GetAsync("https://api.example.com/data");
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            });
        }
        catch (CircuitBreakerOpenException)
        {
            // بازگشت داده کش شده یا پیام خطا
            return "Service temporarily unavailable";
        }
    }
}
مزیت: جلوگیری از اتلاف منابع، بهبود تجربه کاربری، و افزایش resilience سیستم.

45. Retry Pattern چیست؟

پاسخ:

Retry Pattern الگویی برای مدیریت خطاهای موقت است که عملیات ناموفق را چندین بار تکرار می‌کند.

انواع Retry Strategy:
// پیاده‌سازی با Polly
var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .Or<TaskCanceledException>()
    .WaitAndRetryAsync(
        retryCount: 3,
        sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), // Exponential backoff
        onRetry: (outcome, delay, retryCount, context) =>
        {
            Console.WriteLine($"Retry {retryCount} after {delay} seconds");
        });

// ترکیب Retry و Circuit Breaker
var combinedPolicy = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy);

public async Task<ApiResponse> CallExternalApiAsync()
{
    return await combinedPolicy.ExecuteAsync(async () =>
    {
        var response = await _httpClient.GetAsync("https://api.example.com/data");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<ApiResponse>();
    });
}
نکته مهم: فقط برای خطاهای موقت (transient failures) مانند timeout، connection error استفاده کنید، نه برای خطاهای منطقی.

46. Distributed Tracing چیست؟

پاسخ:

Distributed Tracing تکنیکی برای ردیابی درخواست‌ها در سیستم‌های توزیع شده است که امکان مشاهده مسیر کامل یک درخواست در چندین سرویس را فراهم می‌کند.

مفاهیم کلیدی:
پیاده‌سازی با OpenTelemetry:
// نصب پکیج‌ها
// OpenTelemetry
// OpenTelemetry.Extensions.Hosting
// OpenTelemetry.Exporter.Jaeger

// پیکربندی در Program.cs
builder.Services.AddOpenTelemetry()
    .WithTracing(builder =>
    {
        builder
            .AddAspNetCoreInstrumentation()
            .AddHttpClientInstrumentation()
            .AddEntityFrameworkCoreInstrumentation()
            .AddJaegerExporter();
    });

// استفاده در کد
public class OrderService
{
    private static readonly ActivitySource ActivitySource = new("OrderService");
    
    public async Task<Order> CreateOrderAsync(CreateOrderRequest request)
    {
        using var activity = ActivitySource.StartActivity("CreateOrder");
        activity?.SetTag("order.customerId", request.CustomerId);
        
        // منطق ایجاد سفارش
        var order = new Order { CustomerId = request.CustomerId };
        
        // فراخوانی سرویس دیگر
        using var paymentActivity = ActivitySource.StartActivity("ProcessPayment");
        await _paymentService.ProcessPaymentAsync(order.Id, request.Amount);
        
        return order;
    }
}
ابزارها: Jaeger، Zipkin، Azure Application Insights از محبوب‌ترین ابزارهای مشاهده tracing هستند.

47. Event Sourcing چیست؟

پاسخ:

Event Sourcing الگویی است که به جای ذخیره وضعیت فعلی، تمام تغییرات (events) را ذخیره می‌کند و وضعیت فعلی را از روی این رویدادها بازسازی می‌کند.

مزایای Event Sourcing:
پیاده‌سازی ساده:
// تعریف Events
public abstract class Event
{
    public Guid Id { get; set; } = Guid.NewGuid();
    public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}

public class AccountCreated : Event
{
    public Guid AccountId { get; set; }
    public string AccountHolder { get; set; }
    public decimal InitialBalance { get; set; }
}

public class MoneyDeposited : Event
{
    public Guid AccountId { get; set; }
    public decimal Amount { get; set; }
}

public class MoneyWithdrawn : Event
{
    public Guid AccountId { get; set; }
    public decimal Amount { get; set; }
}

// Aggregate
public class Account
{
    public Guid Id { get; private set; }
    public string AccountHolder { get; private set; }
    public decimal Balance { get; private set; }
    
    private readonly List<Event> _events = new();
    
    public void CreateAccount(string accountHolder, decimal initialBalance)
    {
        var @event = new AccountCreated
        {
            AccountId = Guid.NewGuid(),
            AccountHolder = accountHolder,
            InitialBalance = initialBalance
        };
        
        Apply(@event);
        _events.Add(@event);
    }
    
    public void Deposit(decimal amount)
    {
        var @event = new MoneyDeposited { AccountId = Id, Amount = amount };
        Apply(@event);
        _events.Add(@event);
    }
    
    private void Apply(AccountCreated @event)
    {
        Id = @event.AccountId;
        AccountHolder = @event.AccountHolder;
        Balance = @event.InitialBalance;
    }
    
    private void Apply(MoneyDeposited @event)
    {
        Balance += @event.Amount;
    }
    
    public IEnumerable<Event> GetUncommittedEvents() => _events;
}
چالش‌ها: پیچیدگی بیشتر، نیاز به snapshot برای عملکرد، و مدیریت schema evolution.

48. CQRS چیست؟

پاسخ:

CQRS (Command Query Responsibility Segregation) الگویی است که عملیات خواندن (Query) و نوشتن (Command) را از هم جدا می‌کند.

مزایای CQRS:
پیاده‌سازی با MediatR:
// Commands (نوشتن)
public class CreateUserCommand : IRequest<int>
{
    public string Name { get; set; }
    public string Email { get; set; }
}

public class CreateUserCommandHandler : IRequestHandler<CreateUserCommand, int>
{
    private readonly IUserRepository _repository;
    
    public CreateUserCommandHandler(IUserRepository repository)
    {
        _repository = repository;
    }
    
    public async Task<int> Handle(CreateUserCommand request, CancellationToken cancellationToken)
    {
        var user = new User { Name = request.Name, Email = request.Email };
        await _repository.AddAsync(user);
        return user.Id;
    }
}

// Queries (خواندن)
public class GetUserQuery : IRequest<UserDto>
{
    public int UserId { get; set; }
}

public class GetUserQueryHandler : IRequestHandler<GetUserQuery, UserDto>
{
    private readonly IUserReadRepository _readRepository;
    
    public GetUserQueryHandler(IUserReadRepository readRepository)
    {
        _readRepository = readRepository;
    }
    
    public async Task<UserDto> Handle(GetUserQuery request, CancellationToken cancellationToken)
    {
        return await _readRepository.GetUserDtoAsync(request.UserId);
    }
}

// در کنترلر
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly IMediator _mediator;
    
    public UsersController(IMediator mediator)
    {
        _mediator = mediator;
    }
    
    [HttpPost]
    public async Task<ActionResult> CreateUser(CreateUserCommand command)
    {
        var userId = await _mediator.Send(command);
        return CreatedAtAction(nameof(GetUser), new { id = userId }, null);
    }
    
    [HttpGet("{id}")]
    public async Task<ActionResult<UserDto>> GetUser(int id)
    {
        var user = await _mediator.Send(new GetUserQuery { UserId = id });
        return Ok(user);
    }
}
چه زمانی استفاده کنیم؟ زمانی که نیازهای خواندن و نوشتن بسیار متفاوت هستند یا نیاز به مقیاس‌پذیری مستقل داریم.

49. Domain-Driven Design (DDD) چیست؟

پاسخ:

Domain-Driven Design رویکردی برای توسعه نرم‌افزار است که بر روی مدل‌سازی دقیق domain کسب‌وکار تمرکز دارد.

مفاهیم کلیدی DDD:
مثال پیاده‌سازی:
// Value Object
public class Money
{
    public decimal Amount { get; private set; }
    public string Currency { get; private set; }
    
    public Money(decimal amount, string currency)
    {
        if (amount < 0) throw new ArgumentException("Amount cannot be negative");
        Amount = amount;
        Currency = currency ?? throw new ArgumentNullException(nameof(currency));
    }
    
    public Money Add(Money other)
    {
        if (Currency != other.Currency)
            throw new InvalidOperationException("Cannot add different currencies");
        
        return new Money(Amount + other.Amount, Currency);
    }
}

// Entity
public class Order
{
    public int Id { get; private set; }
    public DateTime OrderDate { get; private set; }
    public Money TotalAmount { get; private set; }
    private readonly List<OrderItem> _items = new();
    
    public IReadOnlyList<OrderItem> Items => _items.AsReadOnly();
    
    public void AddItem(Product product, int quantity)
    {
        var existingItem = _items.FirstOrDefault(i => i.ProductId == product.Id);
        if (existingItem != null)
        {
            existingItem.IncreaseQuantity(quantity);
        }
        else
        {
            _items.Add(new OrderItem(product.Id, product.Price, quantity));
        }
        
        RecalculateTotal();
    }
    
    private void RecalculateTotal()
    {
        var total = _items.Sum(i => i.TotalPrice.Amount);
        TotalAmount = new Money(total, "USD");
    }
}

// Domain Service
public class OrderPricingService
{
    public Money CalculateDiscount(Order order, Customer customer)
    {
        if (customer.IsVip && order.TotalAmount.Amount > 1000)
        {
            return new Money(order.TotalAmount.Amount * 0.1m, order.TotalAmount.Currency);
        }
        
        return new Money(0, order.TotalAmount.Currency);
    }
}
مزیت: کد نزدیک‌تر به زبان کسب‌وکار، نگهداری آسان‌تر، و کاهش پیچیدگی در پروژه‌های بزرگ.

50. Clean Architecture چیست؟

پاسخ:

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

لایه‌های Clean Architecture:
ساختار پروژه:
MyProject.Domain/
├── Entities/
│   ├── User.cs
│   └── Order.cs
├── ValueObjects/
│   └── Email.cs
├── Interfaces/
│   └── IUserRepository.cs
└── Services/
    └── DomainService.cs

MyProject.Application/
├── UseCases/
│   ├── CreateUser/
│   │   ├── CreateUserCommand.cs
│   │   └── CreateUserHandler.cs
├── DTOs/
│   └── UserDto.cs
└── Interfaces/
    └── IEmailService.cs

MyProject.Infrastructure/
├── Repositories/
│   └── UserRepository.cs
├── Services/
│   └── EmailService.cs
└── Data/
    └── ApplicationDbContext.cs

MyProject.Web/
├── Controllers/
│   └── UsersController.cs
└── Program.cs
Dependency Injection:
// در Program.cs
// Domain services
builder.Services.AddScoped<IDomainService, DomainService>();

// Application services
builder.Services.AddScoped<ICreateUserHandler, CreateUserHandler>();

// Infrastructure services
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<IEmailService, EmailService>();

// Database
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
قانون وابستگی: لایه‌های داخلی نباید به لایه‌های خارجی وابسته باشند. وابستگی‌ها همیشه به سمت داخل (Domain) هستند.

51. Security Best Practices در ASP.NET Core چیست؟

پاسخ:

مجموعه‌ای از بهترین روش‌ها برای محافظت از برنامه‌های ASP.NET Core در برابر حملات رایج:

بهترین روش‌های امنیتی:
// استفاده از هدرهای امنیتی
app.UseHsts();
app.UseHttpsRedirection();

app.Use(async (context, next) =>
{
    context.Response.Headers.Add("X-Frame-Options", "DENY");
    context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
    context.Response.Headers.Add("Content-Security-Policy", "default-src 'self';");
    await next();
});
به‌روزرسانی: همیشه پکیج‌ها و فریم‌ورک را به‌روز نگه دارید.

52. Integration Testing در ASP.NET Core چیست؟

پاسخ:

Integration Testing نوعی تست است که چندین بخش از برنامه را با هم آزمایش می‌کند تا از صحت تعامل آن‌ها اطمینان حاصل شود.

ویژگی‌های Integration Testing:
// نصب پکیج
// Microsoft.AspNetCore.Mvc.Testing

// مثال تست
public class UserControllerTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly HttpClient _client;

    public UserControllerTests(WebApplicationFactory<Program> factory)
    {
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task Get_ReturnsSuccessAndCorrectContentType()
    {
        // Act
        var response = await _client.GetAsync("/api/users");

        // Assert
        response.EnsureSuccessStatusCode(); // Status Code 200-299
        Assert.Equal("application/json; charset=utf-8", 
            response.Content.Headers.ContentType.ToString());
    }

    [Fact]
    public async Task GetById_WithInvalidId_ReturnsNotFound()
    {
        // Act
        var response = await _client.GetAsync("/api/users/999");

        // Assert
        Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
    }
}
تفاوت با Unit Test: Unit Test یک واحد را ایزوله تست می‌کند، Integration Test تعامل چند واحد را تست می‌کند.

53. gRPC چیست و چه تفاوتی با REST دارد؟

پاسخ:

gRPC یک فریم‌ورک مدرن و با عملکرد بالا برای RPC (Remote Procedure Call) است که توسط گوگل توسعه داده شده.

تفاوت‌های کلیدی:
// تعریف سرویس در .proto
syntax = "proto3";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

// پیاده‌سازی سرویس
public class GreeterService : Greeter.GreeterBase
{
    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

// استفاده از کلاینت
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = "World" });
Console.WriteLine("Greeting: " + reply.Message);
چه زمانی استفاده کنیم؟ برای ارتباط بین میکروسرویس‌ها، برنامه‌های موبایل، و سناریوهای با عملکرد بالا.

54. Blazor چیست و چه تفاوتی با Razor Pages دارد؟

پاسخ:

هر دو برای ساخت برنامه‌های وب در .NET استفاده می‌شوند، اما رویکرد متفاوتی دارند:

Razor Pages:
Blazor:
// کامپوننت Blazor
<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}
Blazor Server vs Blazor WebAssembly: Blazor Server UI را روی سرور رندر می‌کند و با SignalR به‌روزرسانی می‌کند. Blazor WebAssembly کل برنامه را در مرورگر اجرا می‌کند.

55. .NET MAUI چیست؟

پاسخ:

.NET MAUI (.NET Multi-platform App UI) یک فریم‌ورک کراس‌پلتفرم برای ساخت برنامه‌های دسکتاپ و موبایل با یک کدبیس واحد است.

ویژگی‌های .NET MAUI:
// مثال XAML
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp.MainPage">

    <StackLayout>
        <Label Text="Hello, World!" FontSize="32" HorizontalOptions="Center" />
        <Button Text="Click me" Clicked="OnCounterClicked" HorizontalOptions="Center" />
    </StackLayout>

</ContentPage>

// مثال C#
public partial class MainPage : ContentPage
{
    int count = 0;

    public MainPage()
    {
        InitializeComponent();
    }

    private void OnCounterClicked(object sender, EventArgs e)
    {
        count++;
        CounterLabel.Text = $"Current count: {count}";
    }
}
تکامل Xamarin.Forms: .NET MAUI نسل بعدی Xamarin.Forms است با معماری بهتر و عملکرد بالاتر.

56. Top-level Statements در C# چیست؟

پاسخ:

Top-level Statements یک ویژگی در C# 9+ است که امکان نوشتن کد اجرایی را بدون نیاز به متد Main و کلاس Program فراهم می‌کند.

کد قدیمی:
using System;

namespace MyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}
کد با Top-level Statements:
using System;

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

// استفاده از args
if (args.Length > 0)
{
    Console.WriteLine($"Hello, {args[0]}!");
}

// فراخوانی متد async
await Task.Delay(1000);
Console.WriteLine("Done!");
مزایا: کد کوتاه‌تر، یادگیری آسان‌تر برای مبتدیان، و مناسب برای اسکریپت‌نویسی.

57. Record Types در C# چیست؟

پاسخ:

Record یک نوع خاص از کلاس یا struct است که برای مدل‌سازی داده‌های تغییرناپذیر (Immutable) طراحی شده.

ویژگی‌های Record:
// تعریف Record
public record Person(string FirstName, string LastName);

// استفاده
var person1 = new Person("John", "Doe");
var person2 = new Person("John", "Doe");

Console.WriteLine(person1); // Person { FirstName = John, LastName = Doe }
Console.WriteLine(person1 == person2); // True

// With-expression
var person3 = person1 with { LastName = "Smith" };
Console.WriteLine(person3); // Person { FirstName = John, LastName = Smith }
Record Struct: از C# 10 به بعد، می‌توانید record struct برای Value Type های immutable تعریف کنید.

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

پاسخ:

Pattern Matching مجموعه‌ای از ویژگی‌ها در C# است که امکان بررسی ساختار داده‌ها را به صورت مختصر و خوانا فراهم می‌کند.

انواع Pattern Matching:
// مثال با switch expression
public static decimal CalculateToll(object vehicle)
{
    return vehicle switch
    {
        Car c => 2.00m,
        Truck t when t.Weight > 5000 => 10.00m,
        Truck t => 5.00m,
        Bus b => 3.50m,
        { } => throw new ArgumentException("Unknown vehicle"),
        null => throw new ArgumentNullException(nameof(vehicle))
    };
}

// مثال با property pattern
if (order is { Customer: { IsVip: true }, TotalAmount: > 1000 })
{
    ApplyDiscount(order);
}
مزایا: کد خواناتر، کاهش if/else های تودرتو، و مدیریت بهتر انواع داده.

59. Nullable Reference Types چیست؟

پاسخ:

Nullable Reference Types یک ویژگی در C# 8+ است که به کامپایلر کمک می‌کند تا خطاهای NullReferenceException را در زمان کامپایل شناسایی کند.

فعال‌سازی:
// در فایل .csproj
<PropertyGroup>
  <Nullable>enable</Nullable>
</PropertyGroup>

// یا در فایل کد
#nullable enable
قوانین:
public class User
{
    public string FirstName { get; set; }
    public string? MiddleName { get; set; }
    public string LastName { get; set; }

    public User(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}

public void PrintUserName(User user)
{
    Console.WriteLine(user.FirstName.ToUpper());
    
    if (user.MiddleName != null)
    {
        Console.WriteLine(user.MiddleName.ToUpper()); // کامپایلر می‌داند null نیست
    }
    
    // Console.WriteLine(user.MiddleName.ToUpper()); // هشدار کامپایلر
}
هدف: کاهش خطاهای زمان اجرا و افزایش اطمینان از کد.

60. Source Generators در .NET چیست؟

پاسخ:

Source Generators یک ویژگی در کامپایلر Roslyn است که به توسعه‌دهندگان اجازه می‌دهد تا در زمان کامپایل کد C# جدیدی تولید کنند.

کاربردها:
// مثال استفاده از System.Text.Json source generator
[JsonSerializable(typeof(WeatherForecast))]
public partial class MyJsonContext : JsonSerializerContext { }

// استفاده
var forecast = new WeatherForecast { Temperature = 25 };
var json = JsonSerializer.Serialize(forecast, MyJsonContext.Default.WeatherForecast);
مزایا: عملکرد بهتر، کاهش کد دستی، و افزایش اطمینان از کد.

61. .NET Generic Host چیست؟

پاسخ:

Generic Host یک الگوی استاندارد در .NET برای پیکربندی و اجرای برنامه‌های غیر وبی (مانند برنامه‌های کنسولی، سرویس‌های ویندوز) است.

ویژگی‌های Generic Host:
// در Program.cs یک برنامه کنسولی
public class Program
{
    public static async Task Main(string[] args)
    {
        using IHost host = Host.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) =>
            {
                services.AddHostedService<MyBackgroundService>();
                services.AddSingleton<IMyService, MyService>();
            })
            .Build();

        await host.RunAsync();
    }
}
مزیت: یکپارچه‌سازی برنامه‌های غیر وبی با الگوهای مدرن .NET.

62. Assembly در .NET چیست؟

پاسخ:

Assembly واحد اصلی استقرار و نسخه‌بندی در .NET است که می‌تواند یک فایل .dll یا .exe باشد.

محتویات Assembly:
انواع Assembly:
نقش: Assembly ها به CLR اجازه می‌دهند تا کد را بارگذاری، اجرا، و مدیریت کند.

63. Global Assembly Cache (GAC) چیست؟

پاسخ:

GAC یک حافظه کش در سطح ماشین است که برای ذخیره assembly های به اشتراک گذاشته شده بین چندین برنامه استفاده می‌شود.

ویژگی‌های GAC:
نکته: GAC بیشتر مربوط به .NET Framework است. در .NET Core و .NET مدرن، از پکیج‌های NuGet و استقرار مستقل استفاده می‌شود.

64. Reflection در .NET چیست؟

پاسخ:

Reflection مکانیزمی برای بازرسی و دستکاری متادیتای assembly ها، انواع، و اعضای آن‌ها در زمان اجرا است.

کاربردهای Reflection:
// مثال استفاده از Reflection
Type myType = typeof(MyClass);

// ایجاد نمونه
object instance = Activator.CreateInstance(myType);

// فراخوانی متد
MethodInfo myMethod = myType.GetMethod("MyMethod");
myMethod.Invoke(instance, null);

// خواندن مقدار property
PropertyInfo myProperty = myType.GetProperty("MyProperty");
object value = myProperty.GetValue(instance);
عملکرد: Reflection کند است و باید با احتیاط استفاده شود. در صورت امکان، از Source Generators به عنوان جایگزین استفاده کنید.

65. Attribute در C# چیست؟

پاسخ:

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

مثال‌های Attribute:
// تعریف Attribute سفارشی
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyCustomAttribute : Attribute
{
    public string Description { get; set; }

    public MyCustomAttribute(string description)
    {
        Description = description;
    }
}

// استفاده از Attribute
[MyCustom("This is a custom attribute")]
public class MyClass
{
    [MyCustom("This is another one")]
    public void MyMethod() { }
}

// خواندن Attribute با Reflection
var type = typeof(MyClass);
var attribute = (MyCustomAttribute)type.GetCustomAttribute(typeof(MyCustomAttribute));
Console.WriteLine(attribute.Description);
کاربرد: Attribute ها به طور گسترده در ASP.NET Core، Entity Framework، و فریم‌ورک‌های تست استفاده می‌شوند.

66. Delegate و Event چه تفاوتی دارند؟

پاسخ:

هر دو برای پیاده‌سازی الگوی Publisher-Subscriber استفاده می‌شوند:

Delegate:
public delegate void MyDelegate(string message);

public class Publisher
{
    public MyDelegate MyDelegateInstance;

    public void DoWork()
    {
        MyDelegateInstance?.Invoke("Work done");
    }
}

// استفاده
var publisher = new Publisher();
publisher.MyDelegateInstance = (msg) => Console.WriteLine(msg);
publisher.DoWork();
Event:
public class Publisher
{
    public event MyDelegate MyEvent;

    public void DoWork()
    {
        MyEvent?.Invoke("Work done");
    }
}

// استفاده
var publisher = new Publisher();
publisher.MyEvent += (msg) => Console.WriteLine(msg);
publisher.DoWork();

// publisher.MyEvent = null; // خطا! نمی‌توان از خارج کلاس مقداردهی کرد
توصیه: همیشه از Event برای پیاده‌سازی رویدادها استفاده کنید زیرا امنیت و کپسوله‌سازی بیشتری فراهم می‌کند.

67. Extension Methods چیست؟

پاسخ:

Extension Methods به شما اجازه می‌دهند تا متدهای جدیدی به انواع داده موجود اضافه کنید بدون اینکه نیاز به تغییر کد اصلی آن‌ها داشته باشید.

قوانین Extension Methods:
// تعریف Extension Method
public static class StringExtensions
{
    public static int WordCount(this string str)
    {
        return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
    }
    
    public static string ToUrlSlug(this string value)
    {
        return Regex.Replace(value.ToLower(), @"[^a-z0-9_\-]+", "-").Trim("-");
    }
}

// استفاده
string myString = "Hello, world! This is a test.";
int count = myString.WordCount(); // 5

string title = "My Awesome Blog Post";
string slug = title.ToUrlSlug(); // my-awesome-blog-post
کاربرد: LINQ به طور گسترده از Extension Methods استفاده می‌کند (مانند Where, Select, OrderBy).

68. Yield Keyword چیست؟

پاسخ:

کلمه کلیدی yield برای ایجاد متدهای iterator استفاده می‌شود که می‌توانند یک دنباله را به صورت lazy تولید کنند.

ویژگی‌های Yield:
// مثال تولید اعداد زوج
public static IEnumerable<int> GetEvenNumbers(int max)
{
    for (int i = 0; i <= max; i += 2)
    {
        yield return i;
    }
}

// مثال خواندن فایل خط به خط
public static IEnumerable<string> ReadLines(string filePath)
{
    using (var reader = new StreamReader(filePath))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

// استفاده
foreach (var number in GetEvenNumbers(10))
{
    Console.WriteLine(number);
}

foreach (var line in ReadLines("large-file.txt"))
{
    // پردازش هر خط
}
عملکرد: yield برای کار با دنباله‌های بزرگ بسیار بهینه است زیرا از حافظه کمتری استفاده می‌کند.

69. Global Usings در C# چیست؟

پاسخ:

Global Usings یک ویژگی در C# 10+ است که به شما اجازه می‌دهد تا using directive ها را در یک فایل برای کل پروژه تعریف کنید.

تعریف Global Usings:
// در یک فایل جداگانه (مثلاً Usings.cs)
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading.Tasks;
global using Microsoft.AspNetCore.Mvc;
global using MyProject.Models;

// یا در فایل .csproj
<ItemGroup>
  <Using Include="System.Collections.Generic" />
  <Using Include="MyProject.Models" Static="true" />
</ItemGroup>
مزایا: کاهش تکرار using ها در هر فایل و تمیزتر شدن کد.

70. File-scoped Namespaces در C# چیست؟

پاسخ:

File-scoped Namespaces یک ویژگی در C# 10+ است که سینتکس تعریف namespace را ساده‌تر می‌کند.

کد قدیمی:
namespace MyProject.Services
{
    public class MyService
    {
        // ...
    }
}
کد با File-scoped Namespace:
namespace MyProject.Services;

public class MyService
{
    // ...
}
مزایا: کاهش تو رفتگی (indentation) و تمیزتر شدن کد.

71. Memory Management در .NET چگونه کار می‌کند؟

پاسخ:

Memory Management در .NET توسط Garbage Collector (GC) به صورت خودکار انجام می‌شود.

نحوه کار GC:
// مثال مدیریت حافظه
public class MemoryExample
{
    public void CreateObjects()
    {
        // اشیاء کوچک - Generation 0
        var smallObject = new byte[100];
        
        // شیء بزرگ - LOH
        var largeObject = new byte[100000];
        
        // فراخوانی دستی GC (توصیه نمی‌شود)
        GC.Collect();
        GC.WaitForPendingFinalizers();
        
        // بررسی وضعیت حافظه
        long memoryBefore = GC.GetTotalMemory(false);
        Console.WriteLine($"Memory usage: {memoryBefore} bytes");
    }
}
بهترین روش‌ها: از using برای منابع، اجتناب از فراخوانی دستی GC.Collect()، و استفاده از IDisposable برای منابع غیرمدیریت شده.

72. IDisposable Pattern چیست؟

پاسخ:

IDisposable Pattern الگویی برای آزادسازی منابع غیرمدیریت شده (مانند فایل، اتصال پایگاه داده، socket) است.

پیاده‌سازی کامل IDisposable:
public class ResourceManager : IDisposable
{
    private bool disposed = false;
    private FileStream fileStream; // منبع مدیریت شده
    private IntPtr unmanagedResource; // منبع غیرمدیریت شده

    public ResourceManager()
    {
        fileStream = new FileStream("temp.txt", FileMode.Create);
        unmanagedResource = Marshal.AllocHGlobal(100);
    }

    // پیاده‌سازی IDisposable
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    // الگوی Dispose
    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // آزادسازی منابع مدیریت شده
                fileStream?.Dispose();
            }

            // آزادسازی منابع غیرمدیریت شده
            if (unmanagedResource != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(unmanagedResource);
                unmanagedResource = IntPtr.Zero;
            }

            disposed = true;
        }
    }

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

// استفاده با using
using (var manager = new ResourceManager())
{
    // استفاده از منبع
} // Dispose خودکار فراخوانی می‌شود
نکته: همیشه از using statement یا using declaration برای اشیاء IDisposable استفاده کنید.

73. Span<T> و Memory<T> چیست؟

پاسخ:

Span<T> و Memory<T> انواع داده‌ای برای کار بهینه با بلوک‌های حافظه هستند که در .NET Core 2.1+ معرفی شدند.

Span<T>:
// مثال Span<T>
public void ProcessData()
{
    int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    
    // ایجاد Span از بخشی از آرایه
    Span<int> slice = array.AsSpan(2, 5); // عناصر 3 تا 7
    
    // تغییر مقادیر
    for (int i = 0; i < slice.Length; i++)
    {
        slice[i] *= 2;
    }
    
    // کار با string
    string text = "Hello, World!";
    ReadOnlySpan<char> span = text.AsSpan(7, 5); // "World"
    Console.WriteLine(span.ToString());
}
Memory<T>:
// مثال Memory<T>
public async Task ProcessDataAsync()
{
    byte[] buffer = new byte[1024];
    Memory<byte> memory = buffer.AsMemory();
    
    // استفاده در عملیات async
    await WriteToStreamAsync(memory);
}

public async Task WriteToStreamAsync(Memory<byte> memory)
{
    using var stream = new MemoryStream();
    await stream.WriteAsync(memory);
}
عملکرد: استفاده از Span و Memory می‌تواند عملکرد را تا ۵۰٪ بهبود دهد و allocation های غیرضروری را کاهش دهد.

74. ValueTask چیست و چه تفاوتی با Task دارد؟

پاسخ:

ValueTask یک نوع value type است که برای بهینه‌سازی عملکرد در سناریوهای خاص async طراحی شده.

تفاوت‌های کلیدی:
// مثال استفاده از ValueTask
public class CacheService
{
    private readonly Dictionary<string, string> _cache = new();

    public ValueTask<string> GetValueAsync(string key)
    {
        // اگر در کش موجود است، نیازی به async نیست
        if (_cache.TryGetValue(key, out var cachedValue))
        {
            return new ValueTask<string>(cachedValue);
        }

        // اگر در کش نیست، از پایگاه داده بخوان
        return new ValueTask<string>(LoadFromDatabaseAsync(key));
    }

    private async Task<string> LoadFromDatabaseAsync(string key)
    {
        // شبیه‌سازی خواندن از پایگاه داده
        await Task.Delay(100);
        var value = $"Value for {key}";
        _cache[key] = value;
        return value;
    }
}

// استفاده
var service = new CacheService();
string result = await service.GetValueAsync("key1"); // اولین بار از DB
string result2 = await service.GetValueAsync("key1"); // دومین بار از cache
چه زمانی استفاده کنیم؟ زمانی که عملیات اغلب به صورت همزمان تکمیل می‌شود (مانند cache hit، validation).

75. ConfigureAwait(false) چیست؟

پاسخ:

ConfigureAwait(false) به Task می‌گوید که نیازی به بازگشت به context اصلی (مانند UI thread) ندارد.

مشکل بدون ConfigureAwait(false):
// مثال deadlock در WinForms/WPF
public partial class MainForm : Form
{
    private void Button_Click(object sender, EventArgs e)
    {
        // این کد باعث deadlock می‌شود
        var result = GetDataAsync().Result;
        
        // راه حل صحیح
        var result2 = GetDataAsync().ConfigureAwait(false).GetAwaiter().GetResult();
    }

    private async Task<string> GetDataAsync()
    {
        await Task.Delay(1000); // بدون ConfigureAwait(false)
        return "Data";
    }
}

// بهترین روش در کتابخانه‌ها
public class DataService
{
    public async Task<string> GetDataAsync()
    {
        using var client = new HttpClient();
        var response = await client.GetAsync("https://api.example.com/data")
            .ConfigureAwait(false);
        
        return await response.Content.ReadAsStringAsync()
            .ConfigureAwait(false);
    }
}
قانون کلی: در کتابخانه‌ها همیشه از ConfigureAwait(false) استفاده کنید، مگر اینکه نیاز به context داشته باشید.

76. Channels در .NET چیست؟

پاسخ:

Channels یک API برای ارتباط ناهمزمان بین producer و consumer است که جایگزین مدرن برای BlockingCollection محسوب می‌شود.

ویژگی‌های Channels:
// مثال Producer-Consumer با Channel
public class ChannelExample
{
    public async Task RunAsync()
    {
        // ایجاد channel محدود
        var channel = Channel.CreateBounded<int>(10);
        var writer = channel.Writer;
        var reader = channel.Reader;

        // Producer task
        var producerTask = Task.Run(async () =>
        {
            for (int i = 0; i < 100; i++)
            {
                await writer.WriteAsync(i);
                await Task.Delay(10);
            }
            writer.Complete();
        });

        // Consumer task
        var consumerTask = Task.Run(async () =>
        {
            await foreach (var item in reader.ReadAllAsync())
            {
                Console.WriteLine($"Consumed: {item}");
                await Task.Delay(50);
            }
        });

        await Task.WhenAll(producerTask, consumerTask);
    }
}
کاربرد: مناسب برای پیاده‌سازی صف‌های کاری، streaming data، و الگوهای producer-consumer.

77. IAsyncEnumerable چیست؟

پاسخ:

IAsyncEnumerable امکان تولید و مصرف دنباله‌ای از داده‌ها به صورت ناهمزمان را فراهم می‌کند.

مزایای IAsyncEnumerable:
// تولید IAsyncEnumerable
public async IAsyncEnumerable<int> GenerateNumbersAsync(
    int count, 
    [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
    for (int i = 0; i < count; i++)
    {
        cancellationToken.ThrowIfCancellationRequested();
        
        await Task.Delay(100, cancellationToken);
        yield return i;
    }
}

// مصرف با await foreach
public async Task ConsumeNumbersAsync()
{
    await foreach (var number in GenerateNumbersAsync(10))
    {
        Console.WriteLine($"Received: {number}");
    }
}

// مثال خواندن فایل بزرگ
public async IAsyncEnumerable<string> ReadLinesAsync(string filePath)
{
    using var reader = new StreamReader(filePath);
    string line;
    while ((line = await reader.ReadLineAsync()) != null)
    {
        yield return line;
    }
}
کاربرد: مناسب برای API های streaming، پردازش فایل‌های بزرگ، و real-time data processing.

78. Benchmarking در .NET چگونه انجام می‌شود؟

پاسخ:

BenchmarkDotNet محبوب‌ترین کتابخانه برای اندازه‌گیری دقیق عملکرد کد در .NET است.

نصب و استفاده:
// نصب پکیج
// BenchmarkDotNet

// مثال benchmark
[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net80)]
public class StringConcatenationBenchmark
{
    private const int N = 1000;
    private readonly string[] _strings = Enumerable.Range(0, N).Select(i => i.ToString()).ToArray();

    [Benchmark]
    public string StringConcatenation()
    {
        string result = "";
        for (int i = 0; i < N; i++)
        {
            result += _strings[i];
        }
        return result;
    }

    [Benchmark]
    public string StringBuilderConcatenation()
    {
        var sb = new StringBuilder();
        for (int i = 0; i < N; i++)
        {
            sb.Append(_strings[i]);
        }
        return sb.ToString();
    }

    [Benchmark]
    public string StringJoin()
    {
        return string.Join("", _strings);
    }
}

// اجرای benchmark
public class Program
{
    public static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<StringConcatenationBenchmark>();
    }
}
نتیجه: BenchmarkDotNet گزارش دقیقی از زمان اجرا، مصرف حافظه، و تعداد allocation ها ارائه می‌دهد.

79. Profiling در .NET چیست؟

پاسخ:

Profiling فرآیند تحلیل عملکرد برنامه برای شناسایی bottleneck ها و بهینه‌سازی است.

ابزارهای Profiling:
// استفاده از DiagnosticSource برای custom profiling
public class CustomProfiler
{
    private static readonly DiagnosticSource diagnosticSource = 
        new DiagnosticListener("MyApp.Performance");

    public async Task<string> ProcessDataAsync(string data)
    {
        using var activity = diagnosticSource.StartActivity("ProcessData", data);
        
        var stopwatch = Stopwatch.StartNew();
        
        try
        {
            // عملیات اصلی
            await Task.Delay(100);
            var result = data.ToUpper();
            
            return result;
        }
        finally
        {
            stopwatch.Stop();
            diagnosticSource.Write("ProcessData.Duration", stopwatch.ElapsedMilliseconds);
        }
    }
}
نکات مهم: همیشه در محیط Release profile کنید، نه Debug. از production data برای profiling استفاده کنید.

80. Native AOT در .NET چیست؟

پاسخ:

Native AOT (Ahead-of-Time) امکان کامپایل کردن برنامه‌های .NET به کد نیتیو را فراهم می‌کند.

مزایای Native AOT:
فعال‌سازی Native AOT:
// در فایل .csproj
<PropertyGroup>
  <PublishAot>true</PublishAot>
</PropertyGroup>

// دستور publish
dotnet publish -c Release
محدودیت‌ها:
کاربرد: مناسب برای میکروسرویس‌ها، CLI tools، و برنامه‌هایی که نیاز به راه‌اندازی سریع دارند.

81. Trimming در .NET چیست؟

پاسخ:

Trimming فرآیند حذف کد غیرضروری از برنامه برای کاهش حجم نهایی است.

انواع Trimming:
// فعال‌سازی trimming در .csproj
<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
  <TrimMode>link</TrimMode>
</PropertyGroup>

// حفظ کردن assembly خاص از trimming
<ItemGroup>
  <TrimmerRootAssembly Include="MyLibrary" />
</ItemGroup>

// استفاده از attribute برای حفظ کد
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public class MyClass
{
    // این کلاس از trimming محفوظ است
}
احتیاط: Trimming ممکن است کدی را که در runtime استفاده می‌شود (مانند Reflection) حذف کند.

82. ReadyToRun (R2R) چیست؟

پاسخ:

ReadyToRun تکنولوژی pre-compilation است که بخشی از کد را قبل از استقرار کامپایل می‌کند تا راه‌اندازی سریع‌تر شود.

مزایای R2R:
// فعال‌سازی R2R در .csproj
<PropertyGroup>
  <PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>

// دستور publish
dotnet publish -c Release -r win-x64 --self-contained
نکته: R2R حجم فایل نهایی را افزایش می‌دهد اما عملکرد startup را بهبود می‌بخشد.

83. Single File Deployment چیست؟

پاسخ:

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

مزایا:
// فعال‌سازی Single File در .csproj
<PropertyGroup>
  <PublishSingleFile>true</PublishSingleFile>
  <SelfContained>true</SelfContained>
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>

// دستور publish
dotnet publish -c Release
محدودیت: برخی فایل‌ها (مانند native libraries) ممکن است در runtime استخراج شوند.

84. .NET Standard چیست؟

پاسخ:

.NET Standard یک مشخصات (specification) است که API های مشترک بین تمام پیاده‌سازی‌های .NET را تعریف می‌کند.

نسخه‌های .NET Standard:
// تعریف کتابخانه .NET Standard
<PropertyGroup>
  <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
توصیه: برای کتابخانه‌های جدید، از .NET 6+ استفاده کنید. .NET Standard فقط برای سازگاری با .NET Framework ضروری است.

85. Target Framework Moniker (TFM) چیست؟

پاسخ:

TFM یک شناسه استاندارد برای مشخص کردن نسخه و نوع فریم‌ورک .NET است.

مثال‌های TFM:
// Multi-targeting در .csproj
<PropertyGroup>
  <TargetFrameworks>net6.0;net8.0;net48</TargetFrameworks>
</PropertyGroup>

// Conditional compilation
#if NET8_0_OR_GREATER
    // کد مخصوص .NET 8+
#elif NET48
    // کد مخصوص .NET Framework 4.8
#endif
کاربرد: برای ساخت کتابخانه‌هایی که با چندین نسخه .NET سازگار هستند.

86. Package References vs Project References چه تفاوتی دارند؟

پاسخ:

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

Package Reference:
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
Project Reference:
<ProjectReference Include="..\MyLibrary\MyLibrary.csproj" />
<ProjectReference Include="..\Common\Common.csproj" />
انتخاب: از Project Reference برای پروژه‌های داخلی solution و از Package Reference برای کتابخانه‌های خارجی استفاده کنید.

87. NuGet چیست و چگونه کار می‌کند؟

پاسخ:

NuGet مدیر پکیج رسمی .NET است که امکان اشتراک‌گذاری و استفاده از کتابخانه‌ها را فراهم می‌کند.

دستورات NuGet CLI:
// نصب پکیج
dotnet add package Newtonsoft.Json

// حذف پکیج
dotnet remove package Newtonsoft.Json

// به‌روزرسانی پکیج‌ها
dotnet restore

// لیست پکیج‌های نصب شده
dotnet list package

// جستجوی پکیج
dotnet search EntityFramework
ایجاد پکیج NuGet:
// در .csproj
<PropertyGroup>
  <PackageId>MyAwesomeLibrary</PackageId>
  <Version>1.0.0</Version>
  <Authors>Your Name</Authors>
  <Description>A great library for doing awesome things</Description>
  <PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>

// ساخت پکیج
dotnet pack -c Release

// انتشار پکیج
dotnet nuget push MyAwesomeLibrary.1.0.0.nupkg --api-key YOUR_API_KEY --source https://api.nuget.org/v3/index.json
بهترین روش‌ها: همیشه نسخه‌ها را مشخص کنید، از Semantic Versioning استفاده کنید، و dependency ها را به حداقل برسانید.

88. Global Tools در .NET چیست؟

پاسخ:

Global Tools برنامه‌های کنسولی هستند که به صورت سراسری در سیستم نصب می‌شوند و از هر جایی قابل اجرا هستند.

نصب و استفاده از Global Tools:
// نصب global tool
dotnet tool install -g dotnet-ef

// لیست global tools نصب شده
dotnet tool list -g

// به‌روزرسانی global tool
dotnet tool update -g dotnet-ef

// حذف global tool
dotnet tool uninstall -g dotnet-ef
ایجاد Global Tool:
// در .csproj
<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>net8.0</TargetFramework>
  <PackAsTool>true</PackAsTool>
  <ToolCommandName>mytool</ToolCommandName>
  <PackageId>MyGlobalTool</PackageId>
</PropertyGroup>

// Program.cs
public class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine("Hello from my global tool!");
    }
}
مثال‌های محبوب: dotnet-ef، dotnet-aspnet-codegenerator، dotnet-outdated

89. Workloads در .NET چیست؟

پاسخ:

Workloads مجموعه‌ای از ابزارها و SDK های اضافی هستند که برای توسعه انواع خاصی از برنامه‌ها نصب می‌شوند.

انواع Workloads:
// مشاهده workloads نصب شده
dotnet workload list

// نصب workload
dotnet workload install maui

// به‌روزرسانی workloads
dotnet workload update

// حذف workload
dotnet workload uninstall maui

// بازیابی workloads از روی پروژه
dotnet workload restore
مزیت: نصب فقط ابزارهای مورد نیاز و کاهش حجم نصب .NET SDK.

90. .NET CLI چیست؟

پاسخ:

.NET CLI (Command Line Interface) مجموعه‌ای از ابزارهای خط فرمان برای توسعه، ساخت، اجرا، و انتشار برنامه‌های .NET است.

دستورات اصلی:
// ایجاد پروژه جدید
dotnet new console -n MyApp
dotnet new webapi -n MyApi
dotnet new classlib -n MyLibrary

// اجرای پروژه
dotnet run
dotnet run --project MyApp

// ساخت پروژه
dotnet build
dotnet build -c Release

// تست پروژه
dotnet test
dotnet test --logger trx

// انتشار پروژه
dotnet publish -c Release -o ./publish

// اضافه کردن پکیج
dotnet add package Newtonsoft.Json

// مدیریت solution
dotnet sln add MyProject.csproj
dotnet sln list
دستورات پیشرفته:
// مشاهده اطلاعات .NET
dotnet --info
dotnet --list-sdks
dotnet --list-runtimes

// پاک‌سازی
dotnet clean
dotnet nuget locals all --clear

// فرمت کردن کد
dotnet format

// تحلیل کد
dotnet analyze
مزیت: امکان توسعه کراس‌پلتفرم بدون نیاز به IDE خاص و قابلیت اتوماسیون در CI/CD.

91. DevOps و CI/CD در .NET چگونه پیاده‌سازی می‌شود؟

پاسخ:

DevOps و CI/CD در .NET شامل اتوماسیون فرآیند ساخت، تست، و استقرار برنامه‌ها است.

مراحل CI/CD:
// مثال GitHub Actions workflow
name: .NET CI/CD

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup .NET
      uses: actions/setup-dotnet@v3
      with:
        dotnet-version: 8.0.x
        
    - name: Restore dependencies
      run: dotnet restore
      
    - name: Build
      run: dotnet build --no-restore
      
    - name: Test
      run: dotnet test --no-build --verbosity normal
      
    - name: Publish
      run: dotnet publish -c Release -o ./publish
      
    - name: Deploy to Azure
      uses: azure/webapps-deploy@v2
      with:
        app-name: 'my-app'
        publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
        package: './publish'
ابزارها: Azure DevOps، GitHub Actions، Jenkins، GitLab CI

92. Monitoring و Observability در .NET چیست؟

پاسخ:

Monitoring و Observability شامل ابزارها و تکنیک‌هایی برای نظارت بر سلامت و عملکرد برنامه‌های .NET است.

سه رکن Observability:
// پیکربندی Logging در Program.cs
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddApplicationInsights();

// استفاده از ILogger
public class OrderService
{
    private readonly ILogger<OrderService> _logger;
    
    public OrderService(ILogger<OrderService> logger)
    {
        _logger = logger;
    }
    
    public async Task<Order> CreateOrderAsync(CreateOrderRequest request)
    {
        _logger.LogInformation("Creating order for customer {CustomerId}", request.CustomerId);
        
        try
        {
            var order = new Order { CustomerId = request.CustomerId };
            await _repository.SaveAsync(order);
            
            _logger.LogInformation("Order {OrderId} created successfully", order.Id);
            return order;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to create order for customer {CustomerId}", request.CustomerId);
            throw;
        }
    }
}

// Custom Metrics با System.Diagnostics.Metrics
public class OrderMetrics
{
    private static readonly Meter Meter = new("MyApp.Orders");
    private static readonly Counter<int> OrdersCreated = Meter.CreateCounter<int>("orders_created_total");
    private static readonly Histogram<double> OrderProcessingTime = Meter.CreateHistogram<double>("order_processing_duration_ms");
    
    public void RecordOrderCreated()
    {
        OrdersCreated.Add(1);
    }
    
    public void RecordProcessingTime(double milliseconds)
    {
        OrderProcessingTime.Record(milliseconds);
    }
}
ابزارها: Application Insights، Prometheus، Grafana، ELK Stack

93. Security Scanning و Vulnerability Management چیست؟

پاسخ:

فرآیند شناسایی و مدیریت آسیب‌پذیری‌های امنیتی در برنامه‌های .NET:

ابزارهای Security Scanning:
// بررسی آسیب‌پذیری‌ها
dotnet list package --vulnerable

// به‌روزرسانی پکیج‌های آسیب‌پذیر
dotnet add package PackageName --version LatestSecureVersion

// فعال‌سازی NuGet audit در .csproj
<PropertyGroup>
  <NuGetAudit>true</NuGetAudit>
  <NuGetAuditMode>all</NuGetAuditMode>
</PropertyGroup>
بهترین روش: Security scanning را در CI/CD pipeline قرار دهید تا آسیب‌پذیری‌ها زودتر شناسایی شوند.

94. Code Quality و Static Analysis چیست؟

پاسخ:

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

ابزارهای Static Analysis:
// فعال‌سازی Code Analysis در .csproj
<PropertyGroup>
  <EnableNETAnalyzers>true</EnableNETAnalyzers>
  <AnalysisLevel>latest</AnalysisLevel>
  <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

<ItemGroup>
  <PackageReference Include="SonarAnalyzer.CSharp" Version="9.0.0">
    <PrivateAssets>all</PrivateAssets>
    <IncludeAssets>analyzers</IncludeAssets>
  </PackageReference>
</ItemGroup>

// فایل .editorconfig برای قوانین استایل
root = true

[*.cs]
dotnet_analyzer_diagnostic.CA1001.severity = error
dotnet_analyzer_diagnostic.CA1816.severity = warning
مزیت: شناسایی زودهنگام باگ‌ها، بهبود خوانایی کد، و حفظ استانداردهای تیم.

95. Documentation و API Documentation چگونه تولید می‌شود؟

پاسخ:

تولید مستندات خودکار از کد و کامنت‌های XML:

XML Documentation Comments:
/// <summary>
/// محاسبه مجموع دو عدد
/// </summary>
/// <param name="a">عدد اول</param>
/// <param name="b">عدد دوم</param>
/// <returns>مجموع دو عدد</returns>
/// <exception cref="ArgumentException">زمانی که ورودی‌ها نامعتبر باشند</exception>
public int Add(int a, int b)
{
    if (a < 0 || b < 0)
        throw new ArgumentException("Numbers must be positive");
    
    return a + b;
}
تولید مستندات:
// فعال‌سازی XML Documentation در .csproj
<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
  <DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
</PropertyGroup>

// استفاده از Swagger/OpenAPI برای API Documentation
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    
    // اضافه کردن XML comments به Swagger
    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    c.IncludeXmlComments(xmlPath);
});
ابزارها: DocFX، Swagger/OpenAPI، Sandcastle

96. Internationalization (i18n) و Localization (l10n) چیست؟

پاسخ:

فرآیند آماده‌سازی برنامه برای پشتیبانی از زبان‌ها و فرهنگ‌های مختلف:

پیکربندی Localization:
// در Program.cs
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[] { "en-US", "fa-IR", "ar-SA" };
    options.SetDefaultCulture(supportedCultures[0])
           .AddSupportedCultures(supportedCultures)
           .AddSupportedUICultures(supportedCultures);
});

var app = builder.Build();

app.UseRequestLocalization();

// استفاده از IStringLocalizer
public class HomeController : Controller
{
    private readonly IStringLocalizer<HomeController> _localizer;
    
    public HomeController(IStringLocalizer<HomeController> localizer)
    {
        _localizer = localizer;
    }
    
    public IActionResult Index()
    {
        ViewData["Message"] = _localizer["Welcome"];
        return View();
    }
}
فایل‌های Resource:
// Resources/Controllers.HomeController.en-US.resx
Welcome = "Welcome to our website"

// Resources/Controllers.HomeController.fa-IR.resx
Welcome = "به وب‌سایت ما خوش آمدید"
نکات: از CultureInfo برای فرمت اعداد و تاریخ، و از Resource files برای متن‌ها استفاده کنید.

97. Configuration Management در .NET چگونه کار می‌کند؟

پاسخ:

سیستم پیکربندی .NET امکان مدیریت تنظیمات برنامه از منابع مختلف را فراهم می‌کند:

منابع Configuration:
// appsettings.json
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=MyApp;Trusted_Connection=true;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information"
    }
  },
  "MySettings": {
    "ApiKey": "your-api-key",
    "MaxRetries": 3
  }
}

// تعریف کلاس Options
public class MySettings
{
    public string ApiKey { get; set; }
    public int MaxRetries { get; set; }
}

// ثبت در DI
builder.Services.Configure<MySettings>(builder.Configuration.GetSection("MySettings"));

// استفاده در سرویس
public class MyService
{
    private readonly MySettings _settings;
    
    public MyService(IOptions<MySettings> options)
    {
        _settings = options.Value;
    }
    
    public async Task DoWorkAsync()
    {
        // استفاده از _settings.ApiKey و _settings.MaxRetries
    }
}
اولویت: Command Line > Environment Variables > appsettings.{Environment}.json > appsettings.json

98. Environment Management چیست؟

پاسخ:

مدیریت محیط‌های مختلف توسعه، تست، و تولید:

محیط‌های استاندارد:
// تشخیص محیط در کد
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }
    
    if (env.IsProduction())
    {
        // تنظیمات مخصوص تولید
    }
}

// تنظیم متغیر محیطی
// Windows
set ASPNETCORE_ENVIRONMENT=Production

// Linux/Mac
export ASPNETCORE_ENVIRONMENT=Production

// در launchSettings.json
{
  "profiles": {
    "Development": {
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}
بهترین روش: هرگز اطلاعات حساس را در فایل‌های configuration قرار ندهید. از User Secrets یا Azure Key Vault استفاده کنید.

99. Performance Testing چگونه انجام می‌شود؟

پاسخ:

تست عملکرد برای اندازه‌گیری پاسخگویی، پایداری، و مقیاس‌پذیری برنامه:

انواع Performance Testing:
// استفاده از NBomber برای Load Testing
var scenario = Scenario.Create("api_test", async context =>
{
    using var client = new HttpClient();
    var response = await client.GetAsync("https://localhost:5001/api/products");
    
    return response.IsSuccessStatusCode ? Response.Ok() : Response.Fail();
})
.WithLoadSimulations(
    Simulation.InjectPerSec(rate: 100, during: TimeSpan.FromMinutes(5))
);

NBomberRunner
    .RegisterScenarios(scenario)
    .Run();

// مثال Benchmark با BenchmarkDotNet
[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net80)]
public class ApiPerformanceBenchmark
{
    private HttpClient _client;
    
    [GlobalSetup]
    public void Setup()
    {
        _client = new HttpClient();
    }
    
    [Benchmark]
    public async Task<string> GetProducts()
    {
        var response = await _client.GetAsync("https://localhost:5001/api/products");
        return await response.Content.ReadAsStringAsync();
    }
    
    [GlobalCleanup]
    public void Cleanup()
    {
        _client?.Dispose();
    }
}
ابزارها: NBomber، k6، JMeter، Azure Load Testing

100. Future of .NET چیست؟

پاسخ:

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

روندهای آینده:
ویژگی‌های جدید در .NET 8+:
مثال استفاده از ویژگی‌های جدید:
// استفاده از Primary Constructors (C# 12)
public class UserService(IUserRepository repository, ILogger<UserService> logger)
{
    public async Task<User> GetUserAsync(int id)
    {
        logger.LogInformation("Getting user {UserId}", id);
        return await repository.GetByIdAsync(id);
    }
}

// استفاده از Collection expressions (C# 12)
int[] numbers = [1, 2, 3, 4, 5];
List<string> names = ["Alice", "Bob", "Charlie"];

// استفاده از Required members (C# 11)
public class User
{
    public required string Name { get; init; }
    public required string Email { get; init; }
    public string? PhoneNumber { get; init; }
}
توصیه: همیشه با آخرین نسخه‌های .NET به‌روز باشید و از ویژگی‌های جدید برای بهبود کیفیت و عملکرد کد استفاده کنید. 🚀