CodeGym /Kurslar /C# SELF /record açıq bədənlə v...

record açıq bədənlə və record struct

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

1. Giriş

Pozision sintaksisi record-klass üçün sadə hallarda həqiqətən rahatdır:

public record User(string Name, int Age);
Pozision record-klass

Amma bəzən səndə güclü istək yaranır ki, record-a əlavə metodlar, qeyri-standart property-lər əlavə edəsən, access modifier-ləri dəyişəsən, konstruktorun içinə məntiq (məsələn, validation və ya "avtomatik" data çevirmə) əlavə edəsən. Təəssüf ki, pozision yazıda bunları əlavə etməyə yer yoxdur! Artıq açıq bədən sintaksisinə keçmək vaxtıdır, əgər:

  • Record-u metodlarla, property-lərlə və ya əlavə məntiq ilə genişləndirmək istəyirsən.
  • Property-lərin davranışına nəzarət etmək lazımdır (setter, getter, init, validation və s.).
  • Fərqli initializasiya yolları üçün bir neçə konstruktor yaratmaq lazımdır.
  • İnterfeys əlavə etmək və ya xüsusi metodlar implementasiya etmək lazımdır.

record bədənlə qururuq

Sintaksis class-a çox bənzəyir. Bu forma sənə tanışdır:


public class User
{
    /* ... */
}

Sadəcə indi bu record olacaq:


public record User
{
    // Açıq təyin olunmuş property-lər
    public string Name { get; init; }
    public int Age { get; init; }

    // Əlavə məntiq
    public string GetGreeting()
    {
        return $"Salam, mənim adım {Name}-dır və mənim {Age} yaşım var!";
    }

    // Custom konstruktor
    public User(string name, int age)
    {
        Name = name;
        if (age < 0)
            throw new ArgumentException("Age mənfi ola bilməz!");
        Age = age;
    }
}

Maraqlı fakt: Əgər property-ləri açıq təyin edirsənsə, compiler pozision sintaksisdən avtomatik property yaratmır. Hər şey açıq, hər şey sənin nəzarətindədir.

Qarışıq variant: hibrid sintaksis

C# hər iki dünyanı birləşdirməyə imkan verir: sən pozision record elan edə bilərsən və ona bədən əlavə edə bilərsən:


public record User(string Name, int Age)
{
    public string GetGreeting()
    {
        return $"Mən {Name}-am, mənim {Age} yaşım var!";
    }
}
Pozision record bədən və əlavə metodlarla

Bu halda NameAge property-ləri yenə də pozision sintaksis ilə avtomatik yaradılır, sənin əlavə metodların isə rahatlıqla bədənin içində yerləşir.

2. Adi record-lardan fərqlər — bədən nüansları

  • Açıq record konstruktorlara, property-lərə, metodlara tam nəzarət etməyə imkan verir.
  • İnterfeys implementasiya edə bilərsən və ya obyektin identifikasiyası üçün xüsusi müqayisə məntiqi əlavə edə bilərsən.
  • Sadə pozision record-dan fərqli olaraq, yeni property əlavə etmək üçün sadəcə bədənin içində onları elan etmək kifayətdir.

// Yeni başlayanların səhvi!
public record User(string Name, int Age)
{
    public string Name { get; init; } // ← konflikt! Property-nin təkrar elan olunması
}

Yeni başlayanların səhvləri: Bəzi tələbələr eyni anda public record User(string Name, int Age) yazıb, bədənin içində də public string Name { get; init; } property-si əlavə edirlər, elə bilirlər ki, bunlar iki fərqli dəyişəndir. Xeyr! Bu konflikt olacaq (təkrar elan). Ya tam pozision sintaksis istifadə et, ya da property-ləri açıq elan et — qarışdırma.

Praktiki nümunələr

Konsol tətbiqi hazırlamağa davam edirik, burada istifadəçi sifarişlər yaradır. Tutaq ki, sifariş üçün Order adlı class var idi, o belə görünürdü:

public record Order(string Product, int Quantity, double Price);

Tutaq ki, indi bizə quantity üçün validation lazımdır (quantity 1-dən az ola bilməz) və əlavə ümumi məbləğ property-si:


public record Order
{
    public string Product { get; init; }
    public int Quantity { get; init; }
    public double Price { get; init; }
    public double TotalCost => Quantity * Price;

    public Order(string product, int quantity, double price)
    {
        Product = product ?? throw new ArgumentNullException(nameof(product));
        if (quantity < 1)
            throw new ArgumentException("Say 1-dən az ola bilməz!");
        Quantity = quantity;
        Price = price;
    }

    public override string ToString()
        => $"Məhsul: {Product}, Say: {Quantity}, Cəmi: {TotalCost}";
}

Qeyd et ki, property-ləri açıq elan etdik, onları init-setter ilə etdik (dəyişməz obyektlər), avtomatik məbləğ hesablanması əlavə etdik — kod daha çevik oldu!

Proqramda çağırış:

var order = new Order("Velosiped", 2, 15000);
Console.WriteLine(order); // Məhsul: Velosiped, Say: 2, Cəmi: 30000

3. record struct

struct-ların təkamülü

record struct gəlməmişdən əvvəl C#-da struct-lar "sadə işçi atlar" idi — tez kopyalanan, stack-də saxlanılan, qısa “Parcel” datalar üçün (məsələn, koordinatlar və ya rənglər) əla idi. Amma onlar records-un bütün üstünlüklərini dəstəkləmirdi: pozision sintaksis yox idi, with-ifadələri yox idi, default olaraq value ilə müqayisə və digər “şirin şeylər” yox idi.

İndi C#-da struct-ları record stilində elan etmək olar:

public record struct Point(int X, int Y);
record struct üçün pozision sintaksis

Bəs bu bizə nə verir?

  • Avtomatik Equals, GetHashCode, ToString implementasiyası — indi sənin struct-un gözəl müqayisə və çap edə bilir!
  • with-klonlama sintaksisi: var p2 = p1 with { X = 10 };
  • Pozision və ya açıq sintaksis istifadə etmək imkanı.

Müqayisə: klassik struct VS record struct

struct record struct
Pozision sintaksis Yox Bəli
with-ifadə Yox Bəli
Dəyişməzlik Yox (default) Bəli (init)
Value ilə müqayisə Yox (default) Bəli
ToString Standart Gözəl

record struct üçün açıq bədən sintaksisi

Hər şey adi record kimi, sadəcə struct:


public record struct Rectangle
{
    public int Width { get; init; }
    public int Height { get; init; }

    public int Area => Width * Height;

    public Rectangle(int width, int height)
    {
        Width = width > 0 ? width : throw new ArgumentException("En > 0");
        Height = height > 0 ? height : throw new ArgumentException("Hündürlük > 0");
    }

    public void Print()
    {
        Console.WriteLine($"Ölçülər: {Width} x {Height}, sahə: {Area}");
    }
}

İstifadə nümunəsi:

var rect = new Rectangle(10, 7);
rect.Print(); // Ölçülər: 10 x 7, sahə: 70

// Klonlayırıq və eni dəyişirik, orijinal dəyişmir
var wideRect = rect with { Width = 20 };
wideRect.Print(); // Ölçülər: 20 x 7, sahə: 140

record struct xüsusiyyətləri

  • Bu hələ də struct-dır — value type. Təyinatda kopyalanır!
  • Records-un bütün üstünlükləri: value ilə müqayisə, with-klonlama, gözəl ToString.
  • Kiçik, kompakt, dəyişməz data set-ləri üçün tövsiyə olunur, burada heap-də allocation-dan qaçmaq vacibdir.
  • Pozision parametrlər elan edə və ya açıq “bədən” yaza bilərsən.

4. Tipik səhvlər və tələlər

Həddindən artıq mutabillik: record struct sahələri avtomatik dəyişməz etmir, əgər onları adi kimi elan edirsənsə (məsələn, public int Value;). Həqiqətən immutable struct üçün init-setter istifadə et!

Müqayisə: Əgər yeni sahələri əl ilə əlavə edirsənsə (pozision sintaksisə daxil etməmisənsə), bil ki: yalnız konstruktor və ya init-setter ilə olan sahələr avtomatik value müqayisəsində iştirak edir.

Kopyalama: Bu struct-dır, yəni... hər şey kopyalanır! Record class-larla qarışdırma.

with-ifadələrlə qarışıqlıq: Onlar həmişə shallow copy yaradır, yəni iç-içə obyektlər üçün dərin kopyalama etmir.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION