1. NullReferenceException problemi
Demək olar ki, hər bir yeni başlayan (və təkcə onlar yox) C# proqramçısı bu qorxulu mesajla ən azı bir dəfə qarşılaşıb:
System.NullReferenceException: Obyekt referansı obyektin instansiyasına təyin edilməyib.
Budur, klassik bir nümunə:
string salam = null;
Console.WriteLine(salam.Length); // BAM! NullReferenceException
Məna sadədir: sən mövcud olmayan obyektə müraciət etməyə çalışırsan. Yəni dəyişən null-a işarə edir — obyektin yerinə boşluq.
Niyə bu səhvi etmək asandır?
Çünki C#-da əksər referans tipləri tarixən null ala bilirdi. Proqramçılar çox vaxt dəyişənin həqiqətən obyektə işarə etdiyini yoxlamağı unudurdular və nəticədə məşhur NullReferenceException alırdılar.
Əgər proqramçı hər NullReferenceException üçün bir dollar alsaydı, çoxdan öz əməliyyat sistemini yazardı.
Bu niyə problemdir?
Əvvəl öyrəndik ki, int? və ya double? kimi tiplər null ola bilər — yəni "dəyər yoxdur" vəziyyətini açıq göstərmək üçün (məsələn, bazada sahə boş ola bilər).
Ancaq referans tipləri (məsələn, string, istənilən class-lar, massivlər və s.) həmişə null ola bilərdi. Bu, C# yaranandan belədir. Rahatdır, amma təhlükəlidir — çünki dil səni məcbur etmirdi ki, "Bəlkə bu referans boşdur?" deyə düşünəsən.
2. İnkişaf: Nullable Reference Types (NRT)
5 il əvvəl bir yenilik təqdim olundu ki, NullReferenceException ilə mübarizəyə tam fərqli yanaşma gətirdi — Nullable Reference Types (NRT).
string s = "salam"; // not-nullable reference
string? bəlkə = null; // nullable reference
Əsas ideya:
- Heç vaxt null ola bilməyən referans dəyişənləri, null ola bilənlərdən sərt şəkildə ayırmaq.
- Proqramçıya null ilə bağlı potensial problemləri artıq compile zamanı göstərmək, yoxsa runtime-da (artıq gec olanda) yox.
Yeni C# versiyalarında referans dəyişənlərin elanına yanaşma dəyişib: default olaraq null təyin etmək olmaz, yalnız sən açıq şəkildə icazə vermisənsə.
Çox sadə — cəmi bir ? simvolu, amma dəyişənin mənası dərhal dəyişir!
3. Nullable Reference Types-i aktivləşdirmək
Default olaraq bu ciddi sintaksis əksər proyektlərdə deaktivdir, köhnə kodu pozmamaq üçün. Amma müasir Visual Studio, Rider və .NET CLI şablonları artıq NRT ilə gəlir — ya da ən azı bunu tövsiyə edir.
Layihəndə NRT aktivdir ya yox, bunu bilmək üçün .csproj faylında bu sətri tap:
<Nullable>enable</Nullable>
Əgər bu sətir yoxdursa, özün əlavə edə bilərsən — təhlükəsizdir.
Bu kodu necə dəyişir?
- NRT deaktivdirsə (köhnə davranış): string s = null; — heç bir səhv yoxdur, hamı razıdır.
- Aktivdirsə: compiler əsəbləşəcək, əgər null təyin etməyə çalışırsansa ora ki, null olmamalıdır.
4. NRT ilə nümunələr
Sadə nümunə
#nullable enable // Bu sətr bu faylda NRT yoxlamasını aktiv edir
string notNullable = "Salam";
string notNullable2 = null; // KOMPİLYASİYA SƏHVi!
string? nullableString = null; // Problem yoxdur, açıq şəkildə null icazə verdik
Birinci sətrdə obyektə həmişə işarə edən string elan etdik.
Üçüncü sətrdə isə null ola bilən string elan etdik.
null-a yoxlama
void PrintLength(string? s)
{
// Compiler deyəcək: "Bəs s == null olsa?"
Console.WriteLine(s.Length);
// Belə - yaxşıdır
if (s != null)
{
Console.WriteLine(s.Length);
}
}
Compiler artıq yoxlamaları unutmağa qoymur!
Compiler xəbərdarlıqları
Əgər xəbərdarlığı saymasan və yenə də nullable dəyişənə yoxlamasız müraciət etsən — yeni (çox faydalı!) compiler xəbərdarlığı alacaqsan. Bu səhv deyil (proqram yenə də build olacaq), amma sarı "lampa" deyir: "Əminsən, dostum?"
Rejimləri müqayisə edirik:
| C# tipi | Null ola bilər? | Legacy rejimi (NRT-dən əvvəl) | NRT rejimi (#nullable enable) |
|---|---|---|---|
| int | Xeyr | Xeyr | Xeyr |
| int? | Bəli | Bəli | Bəli |
| string | Bəli | Xeyr (həmişə olar) | Xeyr (default olaraq olmaz) |
| string? | Bəli | Xeyr | Bəli |
5. Məsləhətlər: NRT-ni necə və niyə istifadə etməli
- Bug-ların azalması: null səbəbindən gözlənilməz crash-lar azalır, developer və istifadəçi üçün daha çox sevinc.
- Kodun aydınlığı: Dərhal görünür ki, nə boş ola bilər, nə isə həmişə dolu olmalıdır.
- Compiler köməyi: Etiraf edək — o, həqiqətən bizim üçün çalışır! NRT xəbərdarlıqları potensial səhvlər barədə dəyərli məlumatdır.
Harada əvəzolunmazdır
- Böyük layihələrdə, bir neçə nəfər eyni kod üzərində işləyirsə.
- API və public kitabxanalarda — başqalarına nə etmək olar, nə olmaz göstərmək üçün.
- Etibarlılıq vacibdirsə (məsələn, bank tətbiqləri, tibb sistemləri və s.)
6. Tipik səhvlər və tələlər
- "? qoymağı unutdum"
Adi string-ə null təyin edirsən (string s = null;) — compiler əsəbləşir, çünki default olaraq adi string null olmamalıdır. - "? ilə həddini aşdım"
Compiler susmaq üçün bütün dəyişənləri string? edirsən. Məqsəd odur ki, harada həqiqətən boşluq ola bilər, onu diqqətlə işarələyəsən. - "Xəbərdarlığı səhv başa düşdüm"
Xəbərdarlığı saymırsan, sonra NullReferenceException alırsan, halbuki compiler səni qoruyacaqdı.
GO TO FULL VERSION