خیلی خب، برای ویدیوی بعدی، من یک چیزی در مورد **delegate**ها آماده کردم که عمیق‌تر به نحوه‌ی کار
**delegate**ها می‌پردازه تا بهتر متوجه بشید چرا مفید هستن.
و قبل از اینکه بریم سراغ **multicast delegate**ها، که نشون می‌ده **delegate**ها واقعاً چقدر قدرتمند هستن، می‌خواستم
همونطور که گفتم، بیشتر در مورد **delegate**ها بهتون نشون بدم، و برای فهمیدنش، باید **generics** رو متوجه بشید،
حداقل در یک سطح فوق‌العاده، فوق‌العاده، فوق‌العاده ساده، یعنی واقعاً در سطح بالا. ما قراره
خیلی عمیق‌تر به **generics** بپردازیم چون چیزهای زیادی برای یادگیری در موردش هست.
اما قراره در این ویدیو یک مثال خیلی ساده داشته باشیم تا در ویدیوی بعدی گیج نشید،
جایی که در واقع می‌خوام از **generics** در ترکیب با **delegate**ها استفاده کنم.
اوکی.
پس **Yannick** یک فصل کامل رو به **generics** اختصاص داده.
می‌تونید اونو بررسی کنید.
فکر می‌کنم کاملاً مستقله، بنابراین اگه احساس می‌کنید این ویدیو به اندازه‌ی کافی عمیق نیست که **generics** رو
برای درک ویدیوی بعدی متوجه بشید، می‌تونید به فصل **generics** برید و اونو ببینید و بعد به این فصل
**delegate**ها برگردید.
اما فکر می‌کنم کاری که در این ویدیو انجام می‌دیم باید برای فهمیدن مثال بعدی کافی باشه.
اوکی، خب **generics** چی هستن؟
**Generics** راهی هستن برای انعطاف‌پذیرتر و قابل استفاده‌تر کردن کد شما با اجازه‌دادن بهش که با هر
**data type** کار کنه.
**Generics** رو مثل **template**هایی در نظر بگیرید که می‌تونید موقع استفاده، با **type**های مختلف پرشون کنید.
خب چرا باید از **generics** استفاده کنید؟
اول از همه برای انعطاف‌پذیریش، می‌تونید یک **method**، **class** یا **interface** بنویسید و اون رو با
**data type**های مختلف استفاده کنید بدون اینکه نیاز به نوشتن چندین نسخه داشته باشید.
بعد نکته‌ی دوم **type safety** هست.
خب، **generics** کمک می‌کنه خطاها رو در زمان **compile** بگیرید نه در زمان **runtime**، که کد شما رو امن‌تر می‌کنه.
و بعد شماره سه **performance** هست، **generics** از نیاز به **boxing** و **unboxing** هنگام کار با
**value type**ها جلوگیری می‌کنه که می‌تونه **performance** رو بهبود ببخشه.
و این مفهوم چیزیه که **Yannick** قراره عمیق‌تر بهش بپردازه.
خب، یک مثال برای **generic method** چیه؟
خب، تصور کنید می‌خواید یک **method** بنویسید که عناصر یک **array** رو چاپ کنه.
می‌تونید **method**های جداگانه برای هر **type** بنویسید.
مثلاً برای **int**ها، برای **string**ها، برای هر **type** دیگه‌ای که دارید.
یا می‌تونید از یک **generic method** استفاده کنید که با هر **type**ی کار می‌کنه.
خیلی خب، بیاید مثال اینجا رو ببینیم.
پس یک مثال کد کوچک دارم که می‌گه: **public static void print int array**.
و کاری که انجام می‌ده اینه که یک **int array** به عنوان پارامتر می‌گیره.
و بعد از این حلقه‌ی **for each** استفاده می‌کنه تا از تک تک آیتم‌های داخل اون **array** عبور کنه.
و اون آیتم رو روی **console** می‌نویسه.
و بعد یک **method** دیگه دارم که **public static void print string array** هست.
خب، کاری که انجام می‌ده همون کاریه که این **print int array** انجام می‌ده، فقط با این تفاوت که الان این کار رو
با **string**ها انجام می‌ده.
پس به جای استفاده از **int**، از **string** استفاده می‌کنه.
پس یک **array** داریم که **type**ش **string** هست.
و بعد این حلقه‌ی **for each** رو داریم که از تک تک آیتم‌های داخل اون **array** عبور می‌کنه
و اون آیتم رو چاپ می‌کنه.
اوکی.
پس اگه فقط دو تا **type** داشته باشید، خوبه.
درسته؟
اما اگه ندونید چه **type**ی وارد می‌شه و می‌خواید در هر صورت قابل مدیریت باشه، اون موقع
می‌تونید از **generics** استفاده کنید.
پس بیاید این دو **method** رو در یک **method** بسازیم.
و دوباره فقط تصور کنید که این ۲۰ تا **method** هست، اوکی؟
چون دارید ۲۰ تا **type** مختلف رو پوشش می‌دید.
اگه یک **bool** وارد بشه چی؟
اگه یک **double** وارد بشه چی؟
یا اگه یک **array** از **type** هر **class**ی وارد بشه.
حتی **class**ها، درسته.
حتی **object**هایی که پیچیده‌تر از فقط **data type**های ساده مثل **string** و **int** هستن.
پس بیاید یک **method** بسازیم که به ما اجازه بده هر **data type**ی رو بگیریم.
و برای انجام این کار باید از **generics** استفاده کنیم.
خب، یک **generic** چطوری به نظر می‌رسه؟
و ما قبلاً کمی **generics** رو دیدیم.
پس یک **method** **public static** ایجاد می‌کنم.
و از **static keyword** استفاده می‌کنم چون داخل **internal class program** با **static void main** هستم،
می‌خوام بتونم از **method** داخل **main method** استفاده کنم، پس اسم این یکی فقط **print array** خواهد بود.
**Array**.
پس فرقی نمی‌کنه که **string array** باشه یا **int array** یا هر چیز دیگه‌ای.
پس اینجا قسمتیه که **generics** وارد عمل می‌شه.
پس این **angle bracket**ها **t** دارن نشون می‌دن که این یک **generic method** هست.
پس یک **method** که **generic data type** می‌گیره.
پس اینجا می‌تونم بگم فقط **t** نه **task** بلکه **t** و بعد **square bracket**ها.
و بعد یک اسم بهش می‌دم، مثلاً **array**.
و بعد از این **print array** استفاده می‌کنم.
و راستی، باید یک **data type** اضافه کنم.
پس این **void** خواهد بود، چیزی برنمی‌گردونه.
پس این **print array** حالا فقط یک حلقه‌ی **for each** خواهد داشت که از تک تک آیتم‌ها عبور می‌کنه
و هر تک آیتم رو روی **console** می‌نویسه.
پس این کد اینجا تقریباً همون چیزیه که اینجا بود، فقط با این تفاوت که.
حالا به جای گفتن **string**، می‌گیم **t** و **t item in array** و می‌تونید اینجا ببینید که از این **t** استفاده کردیم و از
**t** استفاده کردیم.
پس این **T** فقط یک کاراکتر جایگزین برای هر **data type**ی هست.
پس فقط می‌گه هر **data type**ی که به من بدی، کاری که می‌کنم اینه که چاپش می‌کنم.
اوکی.
پس حالا این به من اجازه می‌ده که برم جلو و **array**ام رو چاپ کنم.
پس اینجا می‌تونم یک **array** از **type int** ایجاد کنم.
و این **array** چند تا عدد خواهد داشت.
پس ۱، ۲، ۳، ۴، ۵، فکر می‌کنم کافی باشه.
اینجوری.
و بعد یک **array** دیگه خواهم داشت که یک **string array** خواهد بود.
و حالا این **string array** مقادیری مثل **one**, **two**, **three** و غیره خواهد داشت.
و راستی، این باید یک **string** باشه، مشخصه.
پس **string array**، ۱، ۲، ۳ و بعد شاید ۴ هم همینطور.
مثل شخصیت مورد علاقه‌مون، **Jin**.
پس اینم از این.
پس حالا کاری که می‌تونیم انجام بدیم اینه که **array** رو یا با **int array**مون چاپ کنیم که کار می‌کنه، یا با
**string array**مون.
و اون هم کار می‌کنه.
اوکی.
پس حالا اینو اجرا می‌کنیم و خواهیم دید.
و در واقع، بیاید مطمئن بشیم که **console dot read key** رو هم داریم تا بتونیم اجراش کنیم و متوقف نشه.
و بتونیم واقعاً ببینیم چه خبره.
پس ۱، ۲، ۳، ۴، ۵، ۱، ۲، ۳، ۴. اوکی، پس می‌بینید حلقه‌ی **for each** ما
براش مهم نبود که یک **int** گرفته، یک **string** گرفته، یا هر چیز دیگه‌ای.
اوکی.
و اینجاست که قسمت **generics** وارد می‌شه.
پس این یک **generic method** هست که یک **generic data type** رو می‌پذیره.
پس هر معنی که بده.
پس در این مورد، یک **array** از هرچیزیه، **string**، **int**، **double**، **class**، **class** خودتون، **custom data type**ی
که دارید ایجاد می‌کنید، با هرچیزی کار می‌کنه.
پس حالا به جای داشتن این **method** و این **method** که کار رو انجام می‌دن، و همیشه باید **method** درست رو **call** کنم تا کار درست رو انجام بدم.
که کار درست رو انجام بدم.
می‌تونستم فقط این کار رو اینجا انجام بدم، یک **method** ایجاد کنم و حالا برای تمام **data type**ها ازش استفاده کنم، که خیلی باحاله.
پس این نحوه‌ی کار **generics** در یک کلامه.
واقعاً ساده‌ان.
اما مثال، همونطور که گفتم، خیلی عمیق‌تر می‌ریم یا **Yannick** خیلی عمیق‌تر به این موضوع می‌پردازه.
اگه احساس می‌کنید این کافی نبود، فصل رو همین الان بررسی کنید، اما اگه احساس می‌کنید: خب، خوبه،
بیاید بپریم به ویدیوی بعدی که قراره از **generics** در مثال **delegate** استفاده کنیم تا یک حس واقعاً خوب
در مورد **delegate**ها پیدا کنیم.
اوکی، پس شما رو در ویدیوی بعدی می‌بینم.