کلاس Generic در #C

یکشنبه 8 فروردین 1395

در این مقاله شما با کلاس Generic و نحوه ی تعریف آن آشنا میشوید و علت بکار گیری آنها در کد مطلع خواهید شد. ما سعی کرده ایم که این مطلب را با مثال و نمونه کد توضیح دهیم تا درک آن راحت و آسان باشد.

 کلاس Generic در #C

در بیشتر موارد ،ما با تعریف یک سری کلاس ها، اقدام به کپسوله سازی رفتارهای یک شی در کد می کنیم و به این ترتیب اشیاء قدرتمندی از این کلاسها می سازیم سپس میتوانیم از آنها نمونه ایجاد کنیم. این کلاسها  به دو روش ایجاد میشوند : هم توسط برنامه نویس و هم توسط زبانی که در آن برنامه نویسی میکنید. ما میتوانیم یک کلاس را با اصلاح  رفتارهایش قدرتمندتر سازیم و آن را به گونه ای برنامه نویسی کنیم که نه تنها از انواع داده ای که برای آنها کد نوشتیم  پیشتیبانی کند بلکه از سایر انواع داده ها نیز پیشتیبانی کند. Generic این اجازه را به ما میدهد. ما میتوانیم به وسیله ی آن کد خود را اصلاح کنیم و  یک لایه اضافی از انتزاع را به آن اضافه میکنیم مطمئنا  برای این کار لایه های اطلاعاتی ما  نباید hard coded باشند.

توضیح و مثال :

مثال زیر را در نظر بگیرید:

1.	public class CustomIntegerStack  
2.	{  
3.	   int pointer = 0;  
4.	   int[] array;  
5.	   public void Push(int p) { }  
6.	   public int Pop() { }  
7.	}  

کلاسی که در مثال بالا آمده است یک ساختار پایه برای  integer stackمیباشد که به ما اجازه میدهد تا نوع داده integer را push  و pop کنیم.

فرایند بالا به خوبی عمل میکند اما نواقص زیر را نیز دارد:

1. ما مجبورهستیم که همه ی بخشهای کلاس را بررسی کنیم تا تعیین کنیم که کدام بخش از کلاس نیاز به تغییر دارد.

2. نیاز داریم که یک فرایند تکراری را برای هر نوع جدید تکرار کنیم.

در اینجا یک کلاسgeneric  از CustomIntegerStack  ایجاد میکنیم. برای این کار باید مراحل زیر را انجام دهید.

1.به جای استفاده از یک نوع مشخص ( که در اینجا integer است ) از حرف T که داده ای از نوع placeholder  است استفاده میکنیم.

2. حرف T را بعد از نام کلاس قرار میدهیم.

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

1.	public class CustomStack<T>  
2.	{  
3.	   int pointer = 0;  
4.	   T[] array;  
5.	   public void Push(T p) { }  
6.	   public T Pop() { }  
7.	}  

Generic Class :

کلاس Generic یک کلاس واقعی نیست. آنها مانند یک قالب برای کلاسها هستند. در اینجا دو قدم مهم وجود دارد که عبارتنداز :

1.ما ابتدا باید یک کلاس واقعی برای آنها  بسازیم.

2.ما میتوانیم از این کلاسهای ساخته شده، نمونه بسازیم.

ایجاد نمونه از یک داده با نوع  generic  نیاز دارد که : یک کلاس از نوع generic  تعریف کنیم، یک constructed type ایجاد کنیم و  یک نمونه از  constructed type بسازیم.

ایجاد یک کلاس از نوع Generic  :

تعریف یک کلاس از نوع Generic  ساده  با کمی تفاوت مشابه تعریف کلاسهای  معمولی است .

1. ما باید علامت < > بعد از نام کلاس قرار دهیم .

2. داخل علامت < >  یک placeholders  قرار میدهیم که نوع داده ی ورودی را مشخص میکند.

ما نوع پارامترها را در بدنه ی کلاس Generic  مورد استفاده قرار میدهیم.

class ClassName<T1, T2>{ }

ایجاد یک constructed type

بعد از ایجاد نوع generic باید به کامپایلر در مورد نوع واقعی آن اطلاع رسانی کنیم. کامپایلر انواع واقعی را میگیرند و یک constructed type ایجاد  میکند. syntax  برای ایجاد constructed type به صورت زیر است:

ClassName < string, int>

ایجاد متغیر و نمونه ها :

 به روش زیر از کلاس مثال بالا نمونه میسازیم :

ClassName < string, int > c1 = new ClassName < string, int > ();
var c1 = new ClassName < string, int > ();

استفاده از Generic در CustomStack 

1.	public class CustomStack<T>  
2.	{  
3.	    public T[] array;  
4.	    public int pointer = 0;  
5.	    private const int maxStack = 10;  
6.	    public bool isStackFull { get { return pointer >= maxStack; } }  
7.	    public bool isStackEmpty { get { return pointer <= 0; } }  
8.	  
9.	    public void Push(T x)  
10.	    {  
11.	        if (!isStackFull)  
12.	        {  
13.	            array[pointer++] = x;  
14.	        }  
15.	    }  
16.	  
17.	    public T Pop()  
18.	    {  
19.	        return !isStackEmpty ? array[--pointer] : array[0];  
20.	    }  
21.	  
22.	    public CustomStack()  
23.	    {  
24.	        array = new T[maxStack];  
25.	    }   
26.	  
27.	    public void Display()  
28.	    {  
29.	        for (int i = pointer-1; i >= 0; i--)  
30.	        {  
31.	            Console.WriteLine("Current Value: {0}", array[i]);  
32.	        }  
33.	    }  
34.	}  
35.	static void Main(string[] args)  
36.	{  
37.	    var intStack = new CustomStack<int>();  
38.	    var strStack = new CustomStack<string>();  
39.	    intStack.Push(1);  
40.	    intStack.Push(2);  
41.	    intStack.Push(3);  
42.	    intStack.Push(4);  
43.	    intStack.Display();  
44.	  
45.	    strStack.Push("Hello world");  
46.	    strStack.Push("Custom stack");  
47.	    strStack.Display();  
48.	  
49.	    intStack.Pop();  
50.	    intStack.Display();  
51.	  
52.	    strStack.Pop();  
53.	    strStack.Display();  
54.	    Console.ReadKey();  
55.	}  

خروجی :

Current Value: 4
Current Value: 3
Current Value: 2
Current Value: 1
Current Value: Hello world
Current Value: Custom stack
Current Value: 3
Current Value: 2
Current Value: 1
Current Value: Hello world

Where Clauses : 

در generic  شرط ها و محدودیت ها در where clauses  لیست میشوند. مانند syntax زیر :

class WhereClauseClass<T1, T2> where T2 : Customer{}                         

متد  Generic  :

متد Generic  میتواند هم در کلاسهای Generic  و هم در کلاسهای  non generic تعریف شود و همچنین میتواند از نوع struct و interface نیز باشد. متدهای Generic  لیستی از پارامترها را میگیرند و همچنین میتوانید برای آنها شرط بگذارید، البته گذاشتن شرط  اختیاری است و میتوان قسمت شرط را حذف کرد. تعریف متد Generic  به صورت قطعه کد زیر میباشد.

public void DisplayData<S, T>(S s, T t) where S : Person { }

فراخوانی  یک متد Generic   

برای فراخوانی یک متد Generic  ، لازم است که تابعی که متد Generic  را فراخوانی میکند با آن ارتباط برقرار کند. به کد زیر دقت کنید.

1.	public void DisplayData<T1, T2>(T1 t1, T2 t2)  
2.	{  
3.	   T1 obj1 = t1;  
4.	   T2 boj2 = t2;  
5.	}  
6.	DisplayData<string, int>(strVal, intVal); 

یک مثال از متد generic  به همراه خروجی : 

در قطعه کد زیر ، یک متد generic  با نام ReverseAndPrint()  در یک کلاس non generic با نام GenericExample تعریف شده است .

1.	public class GenericExample  
2.	{  
3.	    static public void ReverseAndPrint<T>(T[] arr)  
4.	    {  
5.	        Array.Reverse(arr);  
6.	        foreach(T item in arr)  
7.	        {  
8.	            Console.WriteLine("{0}", item.ToString());  
9.	        }  
10.	    }  
11.	}  
12.	  
13.	static void Main(string[] args)  
14.	{  
15.	    var intArr = new int[] { 3, 5, 7 };  
16.	    var strArr = new string[] { "first", "second", "third" };  
17.	    GenericExample.ReverseAndPrint<int>(intArr);  
18.	    GenericExample.ReverseAndPrint<string>(strArr);  
19.	}  
20.	public class GenericExample  
21.	{  
22.	    static public void ReverseAndPrint<T>(T[] arr)  
23.	    {  
24.	        Array.Reverse(arr);  
25.	        foreach(T item in arr)  
26.	        {  
27.	            Console.WriteLine("{0}", item.ToString());  
28.	        }  
29.	    }  
30.	}  
31.	  
32.	static void Main(string[] args)  
33.	{  
34.	    var intArr = new int[] { 3, 5, 7 };  
35.	    var strArr = new string[] { "first", "second", "third" };  
36.	    GenericExample.ReverseAndPrint<int>(intArr);  
37.	    GenericExample.ReverseAndPrint<string>(strArr);  
38.	}  

خروجی :


7
5
3
first
second
third

آموزش سی شارپ

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان
  • C#.net
  • 3k بازدید
  • 5 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید