خوب دوستان در این پست می خوام درباره کلاس های جنریک توضیحاتی رو خدمتتون ارائه بدم:
کلاس های جنریک :
کلاس های جنریک کلاس هایی هستند که می توان انواع داده از نوع های معمولی تا نوع هایی که بوسیله کاربر تولید میشه (مثل کلاس ها، ساختارها و ...) رو به صورت پارامتریک بهشون ارسال کرد.
مثل :
public class Test<T>
{
public void DataType()
{
Type type = typeof(T);
Console.WriteLine("Type is : {0}", type);
}
}
که در این مثال به جای T از نوع های داده ای مثل int, double و یا نوع هایی که به وسیله کاربران تولید شده اند استفاده میشوند
و به صورت زیر به کار می رود :
static void Main(string[] args)
{
Test<Int32> objInt32 = new Test<Int32>();
objInt32.DataType();
Test<Double> objDouble = new Test<Double>();
objDouble.DataType();
Console.ReadLine();
}
و نتیجه زیر حاصل می شود :
Type is : System.Int32
Type is : System.Double
یکی از کلاس های جنریک که توی ویژوال استادیو موجوده، کلاس List<T> هست، کاربرد این کلاس به صورت زیره:
static void Main(string[] args)
{
List<int> objInt = new List<int>();
objInt.Add(1);
objInt.Add(2);
objInt.Add(3);
objInt.Add(4);
objInt.Add(5);
int sum = 0;
foreach (int item in objInt)
{
Console.WriteLine(item);
sum += item;
}
Console.WriteLine("Sum is : {0}", sum);
Console.ReadLine();
}
و خروجی آن به صورت زیر است :
1
2
3
4
5
Sum is : 15
>> خوب حالا شاید این نکته توی ذهنتون اومده باشه که "چرا از کلاس ArrayList (که یک کلاس غیر جنریک هست) استفاده نکردیم؟؟؟!!؟!؟!! اونم که دقیقاً همین کار و انجام می ده!!!! این کلاس میتونه هر نوع داده ای رو تو خودش ذخیره کنه"
درسته، دقیقاً نکته همین جاست، توی این کلاس شما می تونید هر نوع داده ای رو ذخیره کنید با این تفاوت که Type Safe نیست،
>> یعنی چی ؟؟
یعنی اینکه قبل از استفاده از عناصر موجود در ArrayList باید عملیات Casting و یا امثال آن رو انجام بدید.
مثال زیر را در نظر بگیرید :
static void Main(string[] args)
{
ArrayList list = new ArrayList();
// string type
list.Add("hello");
list.Add("C#");
// integer type
list.Add(12);
list.Add(13);
list.Add(20);
// double type
list.Add(12.5);
list.Add(16.5);
foreach (var item in list)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
در این مثال یک ArrayList تعریف شده که چند عضو داره و هر عضو اون نوع های متفاوتی داره، حالا ما می خواهیم از توی این لیست اون هایی که مقادیر عددی صحیح داره رو جمع کنیم !
پس باید عملیات Casting رو انجام بدیم، به صورت زیر:
static void Main(string[] args)
{
ArrayList list = new ArrayList();
// string type
list.Add("hello");
list.Add("C#");
// integer type
list.Add(12);
list.Add(13);
list.Add(20);
// double type
list.Add(12.5);
list.Add(16.5);
int sum = 0;
int num;
foreach (var item in list)
{
if (int.TryParse(item.ToString(), out num))
{
sum += num;
}
}
Console.WriteLine(sum.ToString());
Console.ReadLine();
}
حالا فکر کنید که توی برنامه نویسی به اشتباه عملیات Casting رو انجام نداده باشید اون موقع چه اتفاقی ممکنه بیافته !!؟؟
درسته باعث ایجاد خطای کامپایلر میشه، کامپایلر وقتی به خط sum += int.Parse(item.ToString()); درون حلقه میرسه، چون نمی تونه اون به نوع عدد صحیح تبدیل کنه با خطای (Input string was not in a correct format.) مواجه میشه.
ولی در مقابل اگر از جنریک ها استفاده میکردید، کار به زمان اجرا نمی رسید چون موقعی که یک لیست به صورت جنریک تعریف میشه حتماً باید نوعی رو که واسش به صورت پارامتریک ارسال کردید استفاده کنید،
مثلاً شما یک List<int> تعریف می کنید و زمانی که بخوایید یک نوع رشته ای رو برای اون ارسال کنید (با استفاده از list.add(“hello”)))با خطای زمان کامپایل مواجه میشید.!!!
این هم مزیت جنریک ها، البته این رو هم باید بگم که خود ماکروسافت وقتی که جنریک ها رو تولید کرد، به کلیه برنامه نویسان توصیه کرد که دیگه از جنریک ها استفاده کنند، به خاطر همین مزایاش بود دیگه!!!!
انشا الله در ادامه به بررسی وراثت ها در جنریک ها و تعریف Constraint ها (محدودیت ها) در جنریک ها می پردازیم....
پیروز و سربلند باشید.