در حال بارگذاری...

جنریک‌ها در C#

جنریک‌ها در C# یکی از ویژگی‌های قدرتمند زبان سی‌شارپ هستند که امکان نوشتن کدهایی انعطاف‌پذیر، امن از نظر نوع داده و قابل استفاده مجدد را فراهم می‌کنند. با استفاده از جنریک‌ها، می‌توانیم کلاس‌ها، متدها و ساختارهای داده‌ای طراحی کنیم که با انواع داده‌های مختلف کار کنند بدون آنکه نیاز به تبدیل نوع داده (type casting) یا کپی کردن کد داشته باشیم. این ویژگی به خصوص در پیاده‌سازی کوله‌کشن‌ها مانند List، Dictionary\ و الگوریتم‌های عمومی کاربرد دارد.
در توسعه سی‌شارپ، از جنریک‌ها زمانی استفاده می‌کنیم که یک منطق واحد برای انواع مختلف داده‌ها قابل اعمال باشد. این کار باعث افزایش قابلیت نگهداری، خوانایی و امنیت کد می‌شود و خطاهای زمان اجرا کاهش می‌یابد. همچنین جنریک‌ها با اصول برنامه‌نویسی شیءگرا مانند encapsulation و abstraction سازگار هستند و در طراحی معماری نرم‌افزار به بهبود ماژولاریتی و performance کمک می‌کنند.
در این آموزش، شما یاد خواهید گرفت چگونه کلاس‌ها و متدهای جنریک را تعریف کنید، محدودیت‌های نوع داده (constraints) اعمال کنید و جنریک‌ها را در پروژه‌های واقعی سی‌شارپ استفاده نمایید. همچنین مفاهیمی مانند بهینه‌سازی عملکرد، جلوگیری از خطاهای حافظه و طراحی الگوهای معماری با جنریک‌ها پوشش داده خواهد شد.

مثال پایه

text
TEXT Code
using System;

namespace GenericsDemo
{
// تعریف یک کلاس جنریک ساده
public class Box<T>
{
private T content;

public void Add(T item)
{
content = item;
}

public T Get()
{
return content;
}
}

class Program
{
static void Main(string[] args)
{
// نمونه‌سازی کلاس جنریک با int
Box<int> intBox = new Box<int>();
intBox.Add(42);
Console.WriteLine("محتوای Box: " + intBox.Get());

// نمونه‌سازی کلاس جنریک با string
Box<string> stringBox = new Box<string>();
stringBox.Add("سلام دنیا");
Console.WriteLine("محتوای Box: " + stringBox.Get());
}
}

}

در این مثال، کلاس Box یک کلاس جنریک است که T نوع داده‌ای است که در زمان نمونه‌سازی مشخص می‌شود. متد Add آیتمی از نوع T را به Box اضافه می‌کند و متد Get آن را برمی‌گرداند. در برنامه اصلی، نمونه‌هایی از Box و Box ایجاد شده‌اند تا نشان دهند همان کلاس جنریک می‌تواند برای انواع مختلف داده استفاده شود.
این پیاده‌سازی از نظر نوع داده امن است و کامپایلر بررسی می‌کند که تنها نوع مشخص شده استفاده شود. استفاده از جنریک‌ها باعث کاهش نیاز به type casting، افزایش قابلیت استفاده مجدد و کاهش خطاهای زمان اجرا می‌شود. این روش با اصول OOP و بهترین شیوه‌های توسعه سی‌شارپ همخوانی دارد.

مثال کاربردی

text
TEXT Code
using System;
using System.Collections.Generic;

namespace AdvancedGenericsDemo
{
// تعریف یک Repository جنریک با محدودیت نوع داده
public class Repository<T> where T : class
{
private List<T> items = new List<T>();

public void Add(T item)
{
if (item == null)
throw new ArgumentNullException(nameof(item), "آیتم نمی‌تواند null باشد");
items.Add(item);
}

public T Find(Predicate<T> predicate)
{
return items.Find(predicate);
}

public void DisplayAll()
{
foreach (var item in items)
{
Console.WriteLine(item.ToString());
}
}
}

class Product
{
public string Name { get; set; }
public decimal Price { get; set; }

public override string ToString()
{
return $"{Name} - {Price} تومان";
}
}

class Program
{
static void Main(string[] args)
{
Repository<Product> productRepo = new Repository<Product>();
productRepo.Add(new Product { Name = "Laptop", Price = 70000 });
productRepo.Add(new Product { Name = "Smartphone", Price = 40000 });

Console.WriteLine("تمام محصولات:");
productRepo.DisplayAll();

Product expensiveProduct = productRepo.Find(p => p.Price > 50000);
Console.WriteLine("محصول گران: " + expensiveProduct);
}
}

}

در این مثال، Repository یک کلاس جنریک پیشرفته با محدودیت type constraint where T : class است که اجازه می‌دهد تنها انواع مرجعی استفاده شوند. متد Add با بررسی null و exception handling از خطاهای احتمالی جلوگیری می‌کند. متد Find برای جستجو بر اساس شرط مشخص و DisplayAll برای نمایش تمامی آیتم‌ها استفاده می‌شوند.
کلاس Product به عنوان نمونه واقعی استفاده شده است و متد ToString برای نمایش ساده اطلاعات پیاده‌سازی شده است. این مثال نشان می‌دهد چگونه جنریک‌ها، اصول OOP، الگوریتم‌ها و مدیریت خطا را ترکیب می‌کنند و بهترین شیوه‌های سی‌شارپ را رعایت می‌کنند.

بهترین شیوه‌ها و نکات کلیدی برای جنریک‌ها در C#:

  • از محدودیت‌های نوع داده برای افزایش امنیت استفاده کنید.
  • منابع غیرمدیریت‌شده را در کپسول‌های جنریک ذخیره نکنید.
  • از کوله‌کشن‌های جنریک داخلی مانند List و Dictionary\ استفاده کنید.
  • بررسی null و مدیریت استثناها برای ورودی‌ها اعمال شود.
  • جنریک‌ها را بیش از حد عمومی نکنید.
  • هنگام دیباگ، به نوع داده واقعی توجه کنید.
  • برای بهینه‌سازی عملکرد، از Boxing/Unboxing غیرضروری اجتناب کنید.
  • اعتبارسنجی ورودی‌ها و محافظت از داده‌های حساس برای امنیت الزامی است.

📊 جدول مرجع

سی‌شارپ Element/Concept Description Usage Example
کلاس جنریک کلاسی که می‌تواند با انواع مختلف کار کند public class Box<T> { T content; }
متد جنریک متدی که می‌تواند انواع مختلف داده را پردازش کند public T GetItem<T>(T item) { return item; }
Constraints اعمال محدودیت روی نوع داده where T : class, new()
List<T> کوله‌کشن جنریک List<int> numbers = new List<int>();
Dictionary\<TKey,TValue> کوله‌کشن کلید-مقدار Dictionary\<string,int> ages = new Dictionary\<string,int>();
Predicate<T> delegate برای جستجو یا فیلتر items.Find(p => p.Price > 50000);

خلاصه و گام‌های بعدی:
جنریک‌ها در C# امکان ایجاد کدهای امن، قابل استفاده مجدد و بهینه را فراهم می‌کنند. با استفاده صحیح از کلاس‌ها و متدهای جنریک، محدودیت‌ها، و الگوهای طراحی، می‌توان معماری ماژولار، عملکرد بالا و خطاهای کم در زمان اجرا ایجاد کرد.
برای یادگیری‌های بعدی، مطالعه Stack، Queue، IEnumerable، IComparable و ترکیب جنریک‌ها با Design Patterns توصیه می‌شود. این موضوع به بهبود کیفیت کد، امنیت و performance در پروژه‌های سی‌شارپ کمک می‌کند.

🧠 دانش خود را بیازمایید

آماده شروع

آزمون دانش شما

درک خود از این موضوع را با سوالات کاربردی بسنجید.

4
سوالات
🎯
70%
برای قبولی
♾️
زمان
🔄
تلاش‌ها

📝 دستورالعمل‌ها

  • هر سوال را با دقت بخوانید
  • بهترین پاسخ را برای هر سوال انتخاب کنید
  • می‌توانید آزمون را هر چند بار که می‌خواهید تکرار کنید
  • پیشرفت شما در بالا نمایش داده می‌شود