1
00:00.110 --> 00:00.740
خوش برگشتید.

2
00:00.740 --> 00:02.600
در این ویدیو ما به **Nullable**ها نگاه خواهیم کرد.

3
00:02.600 --> 00:17.030
و **Nullable**ها یک ابزار واقعا قدرتمند هستند که چند سال پیش به **C#** اضافه شد و چیزیه که من اولین بار وقتی از **Kotlin** استفاده کردم باهاش روبرو شدم، که به اصطلاح یک زبان برنامه نویسی جدیدتر هست، و فکر می‌کنم این ویژگی رو از ابتدا در خودش داشت.

4
00:17.030 --> 00:22.160
بنابراین **Nullable**ها اساساً متغیرهایی هستند که می‌تونن **Null** باشن. باشه؟

5
00:22.160 --> 00:26.030
چون متغیرهای معمولی در **C#** نمی‌تونن **Null** باشن. بیایید نگاهی بهش بندازیم.

6
00:26.030 --> 00:34.460
پس اگه من این **int age** رو داشته باشم، مثلاً، و به اون **null** اختصاص بدم، یک **Compiler Error** می‌گیرم. پس مستقیماً می‌گه: "هی، این کار نمی‌کنه."

7
00:34.460 --> 00:42.890
"نمی‌تونی این کار رو بکنی چون نمی‌تونی **Null** رو به **int** تبدیل کنی چون اون یک **Non-nullable Value Type** هست."

8
00:42.890 --> 00:45.710
پس اون یک **Non-nullable Value Type** هست.

9
00:45.710 --> 00:48.590
چطور می‌تونم اون رو به یک **Nullable Value Type** تبدیل کنم؟

10
00:48.590 --> 00:52.490
خب، می‌تونم فقط یک علامت سوال بعد از کلمه کلیدی **int** اضافه کنم.

11
00:52.490 --> 00:56.330
پس حالا این تبدیل به یک **Nullable Value Type** می‌شه.

12
00:56.330 --> 00:59.030
حالا این تبدیل به یک **Nullable int** می‌شه.

13
00:59.030 --> 01:06.860
پس **int** علامت سوال یک **Nullable int** هست. **Nullable** به این معنا که قادر به **Null** بودن هست.

14
01:06.860 --> 01:08.510
اینطوری می‌تونید حفظش کنید.

15
01:08.510 --> 01:09.890
پس اون **Nullable** هست.

16
01:09.890 --> 01:11.990
حالا می‌تونم اون رو **Null** کنم.

17
01:11.990 --> 01:17.420
بیایید چک کنیم که آیا مقداری داره یا نه و بر اساس اون جلو بریم.

18
01:17.420 --> 01:20.300
پس فرض کنید **age** یک مقدار داره.

19
01:20.300 --> 01:28.280
اون وقت من می‌نوشتم به کنسول: "**Age** is: " و بعد **age.Value**.

20
01:28.280 --> 01:36.260
پس چیزی که اینجا می‌بینید اینه که وقتی با **Nullable** کار می‌کنید، می‌تونید به این **Value Property** دسترسی داشته باشید.

21
01:36.260 --> 01:46.460
همین برای **HasValue** هم صادقه. پس این **HasValue** برمی‌گردونه که آیا متغیری که داریم اون رو اعمال می‌کنیم **Null** هست یا نه.

22
01:46.460 --> 01:53.390
پس اگه **Null** باشه، اون وقت **HasValue** **False** برمی‌گردونه. و اگه مقداری داشته باشه، **True** برمی‌گردونه.

23
01:53.390 --> 01:56.180
پس به همین دلیل این دستور **if** اینجا کار می‌کنه.

24
01:56.180 --> 02:02.150
و بعد این **age.Value** مقدار واقعی اون **age** رو به ما خواهد داد. باشه.

25
02:02.150 --> 02:10.820
حالا در بلوک **else**، کاری که قراره انجام بدم اینه که فقط می‌نویسم: "**Age** is not specified" (سن مشخص نشده است)، باشه.

26
02:10.820 --> 02:22.700
پس حالا در مورد ما، قراره بگه: "**Age** is not specified" چون **age** **Null** هست و بنابراین این اجرا نمی‌شه. پس می‌گه: "این **False** هست." بنابراین مستقیماً به بلوک **else** می‌ره.

27
02:22.700 --> 02:26.780
حالا می‌تونید مستقیماً از **age** استفاده کنید.

28
02:26.780 --> 02:29.000
این بلافاصله باعث خطا نخواهد شد.

29
02:29.000 --> 02:35.240
بنابراین می‌تونید مثلاً اینجا **+ age** استفاده کنید. این به طور جالبی باعث خطا نخواهد شد.

30
02:35.240 --> 02:39.200
و این به دلیل **Type Safety** در **C#** هست.

31
02:39.200 --> 02:42.290
پس **C#** در موردش بسیار هوشمنده. فقط می‌گه: "خب، می‌دونی چیه؟

32
02:42.290 --> 02:43.400
من قراره اون رو نادیده بگیرم."

33
02:43.400 --> 02:52.160
اما اگه سعی کنید کاری انجام بدید که، فرض کنید، **age** مقداری نداشته باشه. پس می‌دونیم که در بلوک **else** **age** مشخص نشده.

34
02:52.160 --> 03:07.580
پس نمی‌تونستیم جلو بریم. و فرض کنیم یک متغیر دیگه **int myAge = 35** داریم. برای مثال، نمی‌تونم بگم **int sum** قراره **age + myAge** باشه. باشه، این کار نمی‌کنه.

35
03:07.580 --> 03:15.350
پس باید از **age.Value** استفاده کنیم تا جلو بریم و ازش استفاده کنیم. اما **age.Value** اگه **age** مقداری نداشته باشه، باعث خطا می‌شه.

36
03:15.350 --> 03:25.670
پس اگه **age** در واقع **Null** باشه، باشه، بیایید این کد رو اجرا کنیم و ببینیم چه خطایی قراره بگیریم.

37
03:25.670 --> 03:40.940
پس می‌بینید، ما این **System.InvalidOperationException: Nullable object must have a value** رو می‌گیریم که خطاییه که من دارم می‌گیرم. ما فقط زمانی می‌تونیم به **age.Value** دسترسی داشته باشیم که از **HasValue** استفاده کنیم.

38
03:40.940 --> 03:49.160
و ما فقط می‌تونیم یک **Nullable** رو به یک **Non-nullable** اضافه کنیم اگه در واقع به خود **Value** دسترسی داشته باشیم به جای متغیر.

39
03:49.160 --> 04:02.570
بنابراین، همانطور که دیدید، ما نمی‌تونیم فقط بگیم **age + myAge** چون می‌گه: "**Cannot implicitly convert int? to int. An explicit conversion exists**." (نمی‌توان به‌طور ضمنی **int?** را به **int** تبدیل کرد. یک تبدیل صریح وجود دارد.) آیا **Cast** را فراموش کرده‌اید؟

40
04:02.570 --> 04:14.510
و بعد می‌گه: "**Nullable value type may be null**." (نوع مقدار قابل تهی ممکن است **null** باشد.) پس این ممکنه **Null** باشه و به همین دلیله که می‌گه: چک کن آیا مقداری داره، که ما با این دستور **if** انجام دادیم، و فقط بعد از اون این محاسبه رو انجام بده.

41
04:14.510 --> 04:24.260
بنابراین اگه ما اینجا به جای **HasValue** بگیم **Value**. و بخوایم این محاسبه رو انجام بدیم، می‌تونستیم این کار رو اینجا انجام بدیم.

42
04:24.260 --> 04:32.240
اینجا کار می‌کرد چون می‌تونیم به **Value** دسترسی داشته باشیم چون **HasValue** قبلاً چک کرده که **age** در واقع **Null** نیست.

43
04:32.240 --> 04:43.670
پس چیزی که ما داریم می‌گیم اینه که شما نمی‌تونید "هیچی" رو با چیز دیگه‌ای جمع کنید. باید مطمئن بشید که "هیچی" "هیچی" نیست. پس مقداری داره، یعنی در واقع یک **Value** هست. باشه.

44
04:43.670 --> 04:50.900
پس بیایید به کاربرد در سناریوهای دنیای واقعی نگاه کنیم چون کمی عجیبه، درسته؟ این **Nullable** در مورد چیه؟

45
04:51.080 --> 05:04.220
خب، قضیه اینه که **Nullable Type**ها به ویژه در سناریوهایی مفید هستند که یک متغیر ممکنه قابل اجرا نباشه. یا جاهایی که مقادیر از دست رفته‌اند، مثلاً در تعاملات پایگاه داده.

46
05:04.220 --> 05:08.600
بنابراین فیلدهای پایگاه داده ممکنه اگه تنظیم نشده باشند، **Null** برگردونن.

47
05:08.600 --> 05:19.700
پس فرض کنید ما یک پایگاه داده با **Username**، **Email Address**، **Phone Number** و **Address** کاربر داریم. اما کاربر هرگز شماره تلفن خودش رو وارد نکرده.

48
05:19.700 --> 05:32.150
پس ناگهان ما یک فیلد **Null** در اونجا داریم و نمی‌تونیم اون رو به روش دیگه‌ای مدیریت کنیم مگر اینکه در واقع قادر به مدیریت **Null**ها یا **Nullable** باشیم و **Nullable**ها برای مدیریت چنین مواردی عالی هستند.

49
05:32.180 --> 05:32.750
بسیار خب.

50
05:32.750 --> 05:34.700
و بعد **Form Data** (داده‌های فرم).

51
05:34.700 --> 05:44.960
بنابراین هنگام کار با فرم‌هایی که کاربران ممکنه همه فیلدها رو ارائه ندن، مثل پاسخ‌های اختیاری نظرسنجی، **Nullable Type**ها می‌تونن نشان بدن که آیا پاسخی داده شده یا نه.

52
05:44.960 --> 05:49.670
پس این دوباره تقریباً شبیه مثال پایگاه داده‌ای هست که همین الان بهتون دادم.

53
05:49.670 --> 05:51.350
اما ایده یکسانه.

54
05:51.350 --> 05:57.320
اساساً ما داده‌ها رو نداریم، پس داده‌ها رو از یک پایگاه داده یا از کاربر یا هر چیز دیگه دریافت نمی‌کنیم.

55
05:57.320 --> 06:03.080
و اگه اون رو دریافت نکنیم و به درستی مدیریتش نکنیم، اون وقت برنامه‌مون **Crash** می‌کنه. و این چیزیه که می‌خوایم ازش دوری کنیم.

56
06:03.080 --> 06:06.680
پس مزایای استفاده از **Nullable Type**ها چی می‌تونه باشه؟

57
06:06.680 --> 06:08.360
خب اول از همه، **Safety** (ایمنی).

58
06:08.360 --> 06:19.310
بنابراین از خطاهای زمان اجرا جلوگیری می‌کنه که می‌تونه هنگام کار با انواعی که ممکنه مقداری نداشته باشن، رخ بده، همونطور که همین الان در مثال‌های پایگاه داده، و در مثال فرم هم دیدیم. و بعد **Clarity** (وضوح).

59
06:19.310 --> 06:28.820
بنابراین در کد شما مشخص می‌کنه که یک متغیر ممکنه همیشه مقداری نداشته باشه که قابلیت خوانایی و نگهداری کد رو بهبود می‌بخشه.

60
06:28.820 --> 06:34.250
و گاهی اوقات می‌بینید که یک متد انتظار یک **Nullable** رو داره.

61
06:34.250 --> 06:41.030
بنابراین هر وقت داریم با متدهایی کار می‌کنیم که نیاز به **Nullable** دارن، استفاده از اون‌ها هم منطقیه.

62
06:41.030 --> 07:00.680
بنابراین ما خواهیم دید یا قبلاً دیدیم چند مثال که در اون متد انتظار یک **Nullable** رو داشت، اما همچنین خوب بود که یک **Non-nullable** به عنوان آرگومان داشته باشه. بنابراین این چیزیه که من بیشتر بهتون نشون خواهم داد یا هر بار که در ویدیوهای بعدی باهاش روبرو می‌شیم عمیق‌تر بهش می‌پردازم.