Generic‌ها در سی‌شارپ - بخش دوم

عمومیت با شرط و شروط

در شماره پیش در مورد مفاهیم اولیه Generic‌ها یا همان کلاس‌های عمومی توضیح دادیم و گفتیم این کلاس‌ها چگونه تعریف می‌شود و چه کاربرد‌هایی می‌تواند داشته‌ باشد. در این شماره قصد داریم بیشتر با این مفهوم آشنا شویم و کلاسی را که در شماره پیش نوشتیم توسعه دهیم و مفاهیم دیگر Generic‌ را در آن پیاده‌ کنیم.
کد خبر: ۴۹۹۸۶۱

دامنه گسترش استفاده از Generic‌ها تا کجاست؟ یعنی تا چقدر می‌توانیم از آنها به عنوان یک عنصر اصلی در برنامه‌نویسی استفاده کنیم؟

در شماره پیش فقط در مورد کاربرد Generic‌ها در کلاس‌ها صحبت کردیم و این‌که یک کلاس تعریف کردیم که Generic‌ بود و زمانی که ما می‌خواستیم از آن استفاده کنیم نوع داده مورد نظر خود را به آن ‌دادیم. اما از Generic‌ها می‌توان در جاهای دیگر مثل روابط (interface)، متد‌ها (Method)، ساختارها (structure) استفاده کرد، در زیر برای هر نمونه، مثالی ارائه می‌کنیم:

۱ – Interface :

interface IComparable«T» {

int CompareTo(T other); }

۲ – method :

void Swap«T»(ref T val1, ref T val2) {

T temp = val1;

val1 = val2;

val2 = temp; }

۳ – structure:

struct ComplextType«TFirst, TSecond» {

TFirst _first;

TSecond _second; }

نکته‌ای که در مورد استفاده از Generic‌ها باید در نظر داشته ‌باشید این است، کلاس‌هایی که این رابط‌ها را پیاده می‌کند چگونه پیاده‌سازی می‌شود؟

این کلاس‌ها می‌تواند خود نمونه یک کلاس Generic‌ باشد یا هنگام پیاده‌سازی مشخص کنیم این کلاس همان رابط Generic با این نوع داده خاص است. به مثال‌های زیر دقت کنید:

class Program {

static void Main(string[] args) {

ITest«int» itest1 = new Test1();

ITest«string» itest2 = new Test2«string»();

itest1.Do();

itest2.Do(); } }

interface ITest«T» {

void Do(); }

class Test1 : ITest«int» {

public void Do() {

Console.WriteLine(typeof(int).Name.ToString()); } }

class Test2«T» : ITest«T» {

public void Do() {

Console.WriteLine(typeof(T).Name.ToString()); } }

همان‌طور که در کد بالا مشاهده می‌کنید کلاس Test2 کماکان یک کلاس Generic است، اما کلاس Test1 یک کلاس عادی که رابط ITest را در قالب یک int نشان می‌دهد.

اما شروطی که در استفاده از Generic‌ها می‌توان از آنها استفاده کرد، برای گذاشتن یک شرط در یک کلاس یا یک متدی یا... از کلمه کلیدی where استفاده می‌شود. برای مثال می‌خواهیم شرط کنیم کلاس Generic ما حتما به قالب کلاسی برود که نوع داده آن رابط ITest را پیاده کرده‌ باشد، به مثال زیر دقت کنید:

class Program {

static void Main(string[] args) {

Test1«int» t1 = new Test1«int»();

Test1«Test» t2 = new Test1«Test»(); } }

interface ITest { }

class Test : ITest { }

class Test1«T» where T : ITest{ }

زمانی که می‌خواهید این کد را کامپیال کنید، به تعریف متغیر t1 خطا می‌گیرید؛

The type int cannot be used as type parameter T in the generic type or method

این خطا نشان می‌دهد شما نمی‌توانید کلاس Test1 را به قالب یک نوع داده از نوع int ببرید، اما شما می‌خواهید که کلاس شما فقط به قالب یک کلاس برود که به صورت زیر تعریف می‌شود:

class Test1«T» where T : class{ }

بعضی وقت‌ها که می‌خواهید کلاس خود را به یک قالب ببرید، نیاز دارید یک شیء از آن نوع داده در کلاس خود ایجاد کنید. برای این‌کار باید شرط new() را در تعریف کلاس Generic خود به صورت زیر ذکر کنید:

class Test1«T»

where T : class,new(){

public void doSomthing() {

T t = new T();

Console.WriteLine(t.ToString()); } }

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

در این زمان که کلاس شما نوع داده را به عنوان قالب قبول می‌کند و شما می‌خواهید برای آن دو کلاس شرط بگذارید، نوع داده اول حتما باید class‌ باشد و دومی struct باشد با قابلیت ایجاد یک نمونه از آن در آن کلاس. به کد زیر دقت کنید:

class Test«T, U»

where U : struct 

where T : new() { }

توجه داشته باشید که تمام قواعد ذکر شده برای کاربرد Generic در رابط‌ها، متد‌ها و ساختارها سازگار است.

امیر بهاء‌الدین سبط‌الشیخ

newsQrCode
ارسال نظرات در انتظار بررسی: ۰ انتشار یافته: ۰

نیازمندی ها