1. Eyni ad problemi: field, property, parametr
Yeni başlayanlar tez-tez belə bir vəziyyətlə qarşılaşır ki, property-lərin, constructor parametrinin və private field-lərin adları eyni olur. Bu halda compiler heç nə demir, amma nəticə gözlədiyin kimi olmaya bilər.
Nümunə
public class Student
{
private string name;
public Student(string name)
{
name = name; // "Elə bil ki, hər şey düzgündür..."
}
public void PrintName()
{
Console.WriteLine(name);
}
}
Nə baş verəcək? PrintName() metodunun çap edəcək heç nəyi olmayacaq: private field name elə null olaraq qalacaq! Çünki constructor-un içində name = name; sadəcə lokal parametrə işarə edir, sinifin field-ına yox.
Necə düzəltmək olar
Sinifin field/property-lərinə müraciət üçün this açar sözündən istifadə et:
public Student(string name)
{
this.name = name; // İndi hər şey qaydasındadır!
}
Qeyd: Rider və digər IDE-lər belə səhvləri göstərir — onların tövsiyələrini qulaqardına vurma!
2. Default constructor yoxdur: nə vaxt lazımdır?
Əgər ən azı bir öz constructor-un varsa, compiler artıq "boş" default constructor yaratmır. Bu, xüsusilə obyekt yaratmaq istəyəndə parametr olmadan tez-tez səhvlərə səbəb olur.
Nümunə
public class Book
{
public string Title { get; set; }
// Açıq şəkildə elan olunmuş constructor
public Book(string title)
{
Title = title;
}
}
var book = new Book(); // Compiler: "Bip-bip! Parametrsiz constructor yoxdur!"
Əgər həm parametrsiz, həm də parametrlə obyekt yaratmaq istəyirsənsə, mütləq lazım olan constructor-u əlavə et:
public Book() { }
public Book(string title)
{
Title = title;
}
3. Access modifier-lər: publik adamların şəxsi həyatı
Yeni başlayanların tez-tez etdiyi səhv — access modifier-ləri düşünməmək. Default olaraq sinifin field və metodları private olur, struct-un üzvləri də private olur. Açıq şəkildə yazmamaq və ya unutmaq lazım olan property və ya metoddan sinifdən kənarda istifadə edə bilməməyə gətirib çıxarır.
Nümunə
public class Animal
{
string name; // default olaraq private
public void PrintName()
{
Console.WriteLine(name);
}
}
var animal = new Animal();
animal.name = "Barsik"; // Compilation error!
Compiler private üzvə müraciətə icazə verməyəcək. Düzgün yol — modifier-i açıq şəkildə göstərməkdir:
public string Name;
və ya
private string name;
Daha düzgün istifadə üçün property-lərdən istifadə et:
public string Name { get; set; }
4. Field-i init etməyi unutmaq: null tələsi
Çox yayılmış tələ — sinifin field-i init olunmayıb. Bu, xüsusilə field metodlarda istifadə olunacaqsa və init olunmamışdan əvvəl çağırılacaqsa aktualdır.
Nümunə
public class Cat
{
public string Name;
public void SayHello()
{
Console.WriteLine($"Miyau! Adın uzunluğu {Name.Length} hərf!"); // NullReferenceException ola bilər
}
}
var cat = new Cat();
cat.SayHello(); // Nə faciə!
Name dəyişəni null-dır və Length-ə müraciət NullReferenceException verəcək. Obyekt yaradıldıqdan sonra vəziyyətinə xüsusi diqqət yetir!
Məsləhət: Vacib field-ləri mütləq constructor-da təyin et, property-ləri isə (yeni C#-da) required kimi işarələ.
5. Autosahələrdə sonsuz rekursiya: copy-paste səhvi
Bəzən property-i əl ilə yazanda səhv edirik — məsələn, getter və ya setter-in içində özünə (private field-ə yox) müraciət edirik, bu da loop-a səbəb olur.
Nümunə
public class Dog
{
public int Age
{
get { return Age; } // Ups!
set { Age = value; } // Ups-upps!
}
}
Belə kodda Age çağırılan kimi özü-özünü çağıracaq... sonsuzadək (stack bitənə qədər — rekursiv özünü yemə).
Düzgün yol
Ayrı private field istifadə et:
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
Yaxud autosahədən istifadə et:
public int Age { get; set; }
6. Adların uyğunsuzluğu
Proqramlaşdırmada adların və register-lərin düzgünlüyü vacibdir. C# — register-ə həssas dildir (Case-Sensitive), və Name, name, NAME — üç fərqli identifikatordur.
Həmçinin, əgər field və ya property adını dəyişmisənsə, bütün yerlərdə dəyişdiyinə əmin ol! Rider kodu refactor edə bilər, amma bəzən oxşar adlar varsa, səhvlərdən sığortalamır.
7. Yanlış modifier istifadəsi (static/instance)
Bəzən yeni başlayanlar instance metodları ilə static metodları qarışdırır. Problem o zaman yaranır ki, field/metod-a C# sintaksisinə uyğun olmayan şəkildə müraciət edirsən.
Nümunə
public class MathHelper
{
public static int Add(int a, int b) => a + b;
public int Multiply(int a, int b) => a * b;
}
var sum = MathHelper.Add(2, 3); // OK
var mul = MathHelper.Multiply(2, 3); // Səhv!
Multiply metodu static deyil, onu sinif adı ilə obyekt yaratmadan çağırmaq olmaz:
var helper = new MathHelper();
var mul = helper.Multiply(2, 3); // İndi düz oldu
8. Constructor inheritance zamanı səhvlər
Əgər sinifin başqa sinifdən miras alırsa, unutma ki, base sinifin constructor-u parametr tələb edə bilər.
Nümunə
public class Animal
{
public string Name;
public Animal(string name)
{
Name = name;
}
}
public class Dog : Animal
{
public Dog() { } // Səhv: base sinif name tələb edir!
}
Compiler belə constructor elan etməyə icazə verməyəcək. Base sinifin constructor-un çağırmaq lazımdır:
public class Dog : Animal
{
public Dog(string name) : base(name) { }
}
9. Interface-in bütün üzvlərini implement etməyi unutmaq
Əgər sinifin interface implement edir, amma bütün metodlarını yazmırsansa — compilation error alacaqsan: "Sinif interface-i tam implement etmir".
Nümunə
public interface IWalker
{
void Walk();
void Run();
}
public class Turtle : IWalker
{
public void Walk()
{
Console.WriteLine("Yavaş və əmin addımlarla...");
}
// Ups! Run yaddan çıxdı!
}
IDE xəbərdarlıq edəcək və Turtle compile olmayacaq, bütün interface metodlarını yazmayınca.
10. Init olunmamış obyektlərdən istifadə
C#-da obyektlər açıq şəkildə new ilə yaradılır. Sadəcə dəyişən-sitatı elan etmisənsə, amma obyekt verməmisənsə — o, null-dır. Field/metod-a müraciət edəndə məşhur NullReferenceException alacaqsan.
Nümunə
Student student;
student.PrintName(); // Sürpriz!
Obyekt mütləq init olunmalıdır:
Student student = new Student("Vasilisa");
student.PrintName();
11. Səhv: public field-lər əvəzinə property-lərdən istifadə etməmək
Köhnə "antipattern": bütün sinif field-lərini public elan etmək. Niyə bu pisdir? Field-lər qorunmur, dəyişikliklərə nəzarət yoxdur, encapsulation pozulur!
Nümunə
public class Car
{
public int speed; // Belə etmə!
}
Daha yaxşısı property istifadə etməkdir:
public class Car
{
public int Speed { get; set; }
}
Property-lər yoxlama, məntiq, məhdudiyyət əlavə etməyə imkan verir:
private int speed;
public int Speed
{
get { return speed; }
set
{
if (value < 0) speed = 0;
else speed = value;
}
}
12. "Sehrli ədədlər" və ya sətirlərin qeyri-müəyyən yaradılması
Əgər kodda 42, "İvan", "SomeFile.txt" və s. "sehrli" dəyərləri birbaşa metodun içində görürsənsə — bu potensial səhvdir. Daha yaxşısı constant və ya field istifadə etməkdir.
Nümunə
public class ConfigManager
{
public void Save()
{
File.WriteAllText("config.txt", "some data"); // Sehrli sətir!
}
}
Daha yaxşı:
public class ConfigManager
{
private const string ConfigFileName = "config.txt";
public void Save()
{
File.WriteAllText(ConfigFileName, "some data");
}
}
13. Copy səhvi: dəyişən-sitatlar eyni obyektə işarə edir
C#-da obyekt dəyişənləri — referanslardır. Bir dəyişəni digərinə mənimsədikdə, sadəcə referans kopyalanır, obyektin özü yox. Bu, tez-tez "gözlənilməz" dəyişikliklərə səbəb olur.
Nümunə
Student s1 = new Student("Vasya");
Student s2 = s1;
s1.Name = "Kola";
Console.WriteLine(s2.Name); // "Kola" çap olunacaq!
Niyə? Çünki s1 və s2 — eyni obyektə iki referansdır!
14. Səhvlərdə feedback-in olmaması
Pisdir ki, sinifə icazə verirsən ki, yolverilməz dəyərlər təyin olunsun. Məsələn, mənfi yaş.
Nümunə
public class Human
{
public int Age { get; set; }
}
var h = new Human();
h.Age = -50; // Problem yoxdur...
Sinifin məntiqi mənasız dəyərlərdən qorunmalıdır:
private int age;
public int Age
{
get { return age; }
set
{
if (value < 0)
throw new ArgumentException("Yaş mənfi ola bilməz.");
age = value;
}
}
15. Scope qarışıqlığı
Bəzən dəyişənlər eyni adla müxtəlif scope-larda elan olunur — metodun içində və sinifin field-i kimi.
Nümunə
public class MyClass
{
int value = 10;
public void Foo()
{
int value = 99;
Console.WriteLine(value); // 99 çap olunacaq, 10 yox!
}
}
Sinifin field-ına dəqiq müraciət üçün this.value istifadə et.
16. Metodları override açar sözü olmadan yenidən yazmaq
Əgər base sinifin virtual metodunu override etmək istəyirsənsə, override açar sözünü unutma!
Nümunə
public class Animal
{
public virtual void Speak() => Console.WriteLine("Heyvan danışır");
}
public class Cat : Animal
{
public void Speak() => Console.WriteLine("Miyau!"); // Override deyil!
}
Bu halda base sinifin metodu override olunmayıb: yeni metod sadəcə köhnəni gizlədir (shadowing), bu da base referanslarla işləyəndə gözlənilməz nəticələrə gətirib çıxara bilər.
Düzgün yol:
public override void Speak() => Console.WriteLine("Miyau!");
17. Constructor-da virtual metod çağırmaq
Bu, compilation error olmasa da, tez-tez çətin tapılan bug-lara səbəb olur. Əgər base sinifin constructor-unda virtual metod çağırılırsa və bu metod child-da override olunubsa — çağırılan anda child sinifin field-ləri init olunmamış ola bilər.
Nümunə
public class Animal
{
public Animal()
{
Speak();
}
public virtual void Speak()
{
Console.WriteLine("Heyvan...");
}
}
public class Cat : Animal
{
public string Name { get; set; } = "Barsik";
public override void Speak()
{
Console.WriteLine($"Miyau! Mən {Name}");
}
}
Cat cat = new Cat();
// Speak() çağırılan anda Cat constructor-u hələ işə düşməyib, Name hələ null-dır!
18. Obyekti yalnız constructor ilə təsvir etmək (property olmadan)
Əgər sinifdə yalnız constructor varsa və obyekt yaradıldıqdan sonra dəyişmək olmursa — dəyişməz obyektlər üçün yaxşıdır, amma həmişə rahat deyil. Çox vaxt istifadəçiyə property-ləri dəyişmək imkanı vermək daha yaxşıdır (və ya heç olmasa bəzilərini).
19. Naming conventions qaydalarına məhəl qoymamaq
Sinif adları böyük hərflə, metodlar da böyük hərflə, field-lər kiçik və alt xəttlə (və ya camelCase ilə), constant-lar isə BÜTÜN BÖYÜK hərflə yazılır. Eyni stil istifadə etmək oxunaqlılığı artırır və təsadüfi səhvlərin riskini azaldır!
20. İstifadə olunmayan field və metodlar
Əgər bir field elan etmisənsə, amma heç yerdə istifadə etmirsənsə — bu "ölü kod"dur. IDE belə halları göstərə bilər. Nə qədər az "ölü zona" olsa, tətbiqi saxlamaq bir o qədər asan olar!
GO TO FULL VERSION