CodeGym /Kurslar /C# SELF /required property-lər və field property-lər

required property-lər və field property-lər

C# SELF
Səviyyə, Dərs
Mövcuddur

1. Giriş

C#-da property-siz proqram yazmaq olar, amma bu, sanki Ağ Evdə roliklərlə gəzmək kimidir — mümkündür, amma heç rahat deyil. İndi artıq əlavə getter və setter-lər olmadan qısa sintaksisə öyrəşmişik, amma app-imiz “ciddi” modellərlə işləməyə başlayanda (məsələn, sistemdə istifadəçini təsvir edən User class-ı), vacib olur ki, bütün lazım olan datalar həqiqətən də mövcud olsun.

Məsələn, əgər belə bir class-ımız varsa:

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Property-ləri initialize etməyi asanlıqla unuda bilərik:

User user = new User(); // Name null olacaq, Age = 0

Nəticədə, hardasa on ekran və yüz logic döngəsindən sonra məşhur NullReferenceException alacaqsan və günahkarı tapmaq üçün çox vaxt itirəcəksən.

init-only property-ləri xatırlayaq

Bəli, yalnız yaradılarkən initialize etmək olar:

public string Name { get; init; }

Amma bu sintaksislə belə, heç kim class istifadəçisini dəyər ötürməyə məcbur etmir — əksər default constructor-lar field-ləri default dəyərlə initialize edir (null, 0 və s.).

Bəs necə edək ki, proqramçı və ya özümüz vacib dəyəri unutmayaq? Məhz bunun üçün C# 11-də required modifier-i icad olunub.

2. required property-lər: sərt initialize qaydası

required modifier-i kompilyatora deyir ki, obyekt yaradılarkən bu property mütləq şəkildə təyin olunmalıdır. Sadə dillə desək, əgər belə property initialize olunmayıbsa — kompilyator kodu buraxmayacaq, IDE isə qorxulu qırmızı xətt çəkəcək.


public class User
{
    public required string Name { get; set; }
    public int Age { get; set; }
}
required ilə mütləq property

Gəlin istifadəçi yaradaq:

// Kompilyasiya xətası: Name property-si initialize olunmalıdır!
User user1 = new User();

Və ya belə:


// Kompilyasiya xətası: required property Name göstərilməyib
User user2 = new User { Age = 18 };

Doğru yol isə belədir:

User user3 = new User { Name = "Hermiona", Age = 18 };

required necə işləyir?

required modifier-i kompilyatora deyir: “Obyektin constructor-u bitəndən sonra, bu property mütləq təyin olunmalıdır”.

Bu həm adi property-lər, həm də init-only üçün işləyir:

public required string Name { get; init; }

Əgər öz constructor-un varsa və required property üçün dəyər təyin edirsənsə, qayda pozulmur.

Tipik yoxlama sxemi

Ssenari Kompilyator razıdır?
required property təyin olunmayıb ❌
Obyekt initializer-də təyin olunub ✔️
Constructor-da təyin olunub ✔️

Bizim “İt” modelində nümunə

public class Dog
{
    public required string Name { get; set; }
    public int Age { get; set; }
}

Dog dog = new Dog { Name = "Bobik", Age = 5 }; // Hər şey ok!
Dog badDog = new Dog { Age = 2 }; // Xəta! Name göstərilməyib

required harada həqiqətən kömək edir?

  • Layer-lər arasında DTO ötürüləndə: Əgər API-n varsa, input-da həmişə bütün vacib field-lər gəlməlidir.
  • Vacib atributlu kompleks modellər: Məsələn, Product-da mütləq SKU, Order-də mütləq nömrə.
  • Müsahibə və kod review zamanı: Belə sintaksis göstərsən, yəqin ki, kodunu hörmətlə (və bir az paxıllıqla) oxuyacaqlar.

3. required və constructor-lar necə işləyir?

Bəzən öz constructor-un yazırsan. Əgər required property constructor-da və ya obyekt initializer-də initialize olunmasa nə baş verəcək? Kompilyator xəta verəcək.


public class Article
{
    public required string Title { get; set; }
    public required string Author { get; set; }

    public Article()
    {
        // Əgər Title və Author initialize olunmasa — kompilyasiya xətası!
        // Belə etmək olar:
        Title = "Başlıqsız";
        Author = "Naməlum";
    }
}

Əgər constructor required property-lərə dəyər verir — hər şey qaydasındadır. Əks halda, bu field-ləri obyekt initializer-lə (new Article { ... }) initialize etməlisən.

İstifadə spesifikası

  • required yalnız property-lərlə işləyir, field-lərlə yox.
  • required miras alınmır — əgər base property required-dursa, amma child-da required yazmasan, kompilyator narazı olmur (amma yaxşı practice odur ki, child-da da required yazasan).
  • required avtomatik field-lərə və ya property-dən başqa heç nəyə tətbiq edilə bilməz.

4. Property-lərin arrow sintaksisi

C#-ın yeni versiyaları ilə dev-lər daha qısa və ifadəli kod yazmağa can atır. Property-lər üçün ən gözəçarpan yeniliklərdən biri — arrow sintaksisi (yəni expression-bodied properties).

Bəzən elə property yazmaq istəyirsən ki, sadəcə bir dəyəri qaytarsın, əlavə logic olmadan. Əvvəllər bunun üçün tam getter yazmaq lazım idi:

public int Age
{
    get { return birthYear > 0 ? DateTime.Now.Year - birthYear : 0; }
}

İndi isə çox daha qısa yazmaq olar — arrow (=>) istifadə edərək:


public int Age => birthYear > 0 ? DateTime.Now.Year - birthYear : 0;

Bu sintaksisə expression-bodied property deyilir. Sadə hesablama üçün əladır və kodu daha kompakt edir.

get və set ilə istifadə nümunəsi

public class Book
{
    private string _title;

    public string Title
    {
        get => _title;
        set => _title = value.Trim();
    }
}

Burada get field-ın dəyərini qaytarır, set isə əvvəlcə artıq boşluqları silib təyin edir.

Yalnız get (read-only) istifadə nümunəsi:

Əgər property read-only-dursa — heç bir curly bracket olmadan, sadəcə => ilə yaza bilərsən.

public class Person
{
    private string name = "Mark Tven";

    // Yalnız oxumaq üçün: hesablama property-si
    public string Name => name.ToUpper();
}

Burada Name property-si yalnız oxunur — həmişə name-i böyük hərflərlə qaytarır.

5. Property-lər üçün field açar sözü

C# 14-dən əvvəl, əgər avtomatik property-nin gizli field-ına setter və ya getter-də müraciət etmək istəyirdin (məsələn, recursion-dan qorunmaq və ya əlavə logic yazmaq üçün) — bunu etmək olmurdu. Field-ı ayrıca elan etməli idin.

C# 14 avtomatik property-nin gizli field-ına field açar sözü ilə müraciət etməyə imkan verir:


public class Person
{
    public string Name
    {
        get => field; // field — Name property-nin gizli field-ıdır
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("Ad boş ola bilməz!");
            field = value; // _name əvəzinə field istifadə edirik
        }
    }
}

Əvvəl belə yazmalı idin:

private string _name;
public string Name
{
    get => _name;
    set
    {
        if (string.IsNullOrWhiteSpace(value))
            throw new ArgumentException("Ad boş ola bilməz!");
        _name = value;
    }
}

Bir dəyişən elan etməyə ehtiyac qalmadı. Kod nə qədər qısa olsa, bir o qədər yaxşıdır.

Bəzən property daxilində məhz field-a müraciət etmək niyə vacibdir?

  • Bəzən dəyərin harada və necə saxlanmasını tam nəzarətdə saxlamaq lazımdır (məsələn, obyektin kopyasını vermək, nəticəni cache etmək və ya lazy-loading etmək istəyirsənsə).
  • Əgər attribute və ya reflection istifadə edirsənsə — field adı lazım ola bilər.
  • Bəzi (de)serialization və ya performance tuning hallarında dəyərin saxlanmasına daha çox nəzarət etmək istəyirsən.

İstifadə nümunələri:

Setter-də data validation

public double Grade
{
    get => field;
    set
    {
        if (value < 0 || value > 5)
            throw new ArgumentOutOfRangeException("Qiymət 0-dan 5-ə qədər olmalıdır");
        field = value;
    }
}

Dəyərin dəyişməsinə görə statistika

public int StepCount
{
    get => field;
    set
    {
        if (value > field)
        {
            Console.WriteLine($"Ura! Sən {value - field} addım çox atmısan!");
        }
        field = value;
    }
}

Lazy Load

public string Data
{
    get
    {
        if (field == null)
            field = LoadDataFromDatabase();
        return field;
    }
    set => field = value;
}

6. Tipik səhvlər və nüanslar

Səhv №1: required property-ni initialize etməyi unutmaq.
Kompilyator belə kodu buraxmayacaq və build zamanı dərhal xəta verəcək, bu da proqram işləyərkən problemlərin qarşısını alır.

Səhv №2: required property-lər constructor-da tam initialize olunmayanda işləmir.
Əgər constructor bütün vacib property-lər üçün dəyər almırsa, kompilyator sənə xəbər verəcək ki, nəsə yaddan çıxıb.

Səhv №3: required-i const və ya readonly ilə istifadə etmək cəhdi.
Bu modifier-lər uyğun deyil — required yalnız adi property-lərə tətbiq oluna bilər. Onları birləşdirməyə cəhd etsən, xəta alacaqsan.

2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
required xassələri olan sinifin yaradılması
required xassələri olan sinifin yaradılması
2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
Getter və setter-lərdə field istifadə edərək istifadəçi məntiqi
Getter və setter-lərdə field istifadə edərək istifadəçi məntiqi
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION