11-bo‘lim

struct va record

Qiymat turlarini o'zingiz yaratish, struct va class farqi, record turlari, tenglik qoidalari, with ifodasi va qaysi birini tanlash.

🕑 11 daqiqa o‘qish 📄 721 so‘z 👁 3 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. struct - o'zingiz yaratgan qiymat turi
  2. struct qachon kerak
  3. record - ma'lumot saqlash uchun
  4. with - nusxa olib, bir qismini o'zgartirish
  5. record struct
  6. Uchtasini solishtirish
  7. enum - nomlangan qiymatlar to'plami
  8. Xulosa

Shu paytgacha class bilan ishladik. C# da yana ikkita tur e'lon qilish usuli bor va ularning har biri boshqa muammoni hal qiladi.

struct - o'zingiz yaratgan qiymat turi #

struct class ga o'xshaydi, lekin u qiymat turi: nusxalanadi, havola qilinmaydi.

CSHARP
var a = new Nuqta(3, 4);
var b = a;                    // NUSXA olinadi

b.X = 100;

Console.WriteLine($"a = ({a.X}, {a.Y})");
Console.WriteLine($"b = ({b.X}, {b.Y})");
Console.WriteLine($"a dan boshgacha masofa: {a.Masofa():F2}");

struct Nuqta(double x, double y)
{
    public double X { get; set; } = x;
    public double Y { get; set; } = y;

    public double Masofa() => Math.Sqrt(X * X + Y * Y);
}
Natija
a = (3, 4)
b = (100, 4)
a dan boshgacha masofa: 5.00

b ni o'zgartirish a ga ta'sir qilmadi - 3-bo'limdagi qiymat turi qoidasi.

Xuddi shu kodni class bilan yozsangiz, natija butunlay boshqacha bo'ladi:

CSHARP
var a = new Nuqta(3, 4);
var b = a;                    // HAVOLA nusxalanadi

b.X = 100;

Console.WriteLine($"a = ({a.X}, {a.Y})");
Console.WriteLine($"b = ({b.X}, {b.Y})");

class Nuqta(double x, double y)
{
    public double X { get; set; } = x;
    public double Y { get; set; } = y;
}
Natija
a = (100, 4)
b = (100, 4)

Bitta so'z - struct o'rniga class - natijani butunlay o'zgartirdi.

Bu xatoni topish juda qiyin

Ikkala kod ham kompilyatsiya qilinadi va xato bermaydi. Farq faqat ishlash paytida ko'rinadi.

Agar struct ni metodga uzatib, uni o'zgartirsangiz, asl nusxa o'zgarmaydi va bu ko'pincha kutilmagan bo'ladi.

Shuning uchun zamonaviy tavsiya: struct ni o'zgarmas qiling - { get; init; } yoki readonly struct ishlating. Shunda chalkashlik uchun sabab qolmaydi.

struct qachon kerak #

ShartIzoh
Kichik (odatda 16 baytgacha)Nusxalash arzon bo'lsin
Mantiqan bitta qiymatNuqta, rang, pul miqdori
O'zgarmasYaratilgandan keyin o'zgarmasin
Juda ko'p yaratiladiXotira yukini kamaytiradi

Bu shartlarning hammasi bajarilmasa - class ishlating.

Nega kichik bo'lishi kerak

struct har uzatilganda to'liq nusxalanadi. Ichida 10 ta maydon bo'lsa, har bir metod chaqiruvida 10 ta qiymat ko'chiriladi.

class da esa faqat havola (8 bayt) uzatiladi, obyekt qanchalik katta bo'lishidan qat'i nazar.

Ya'ni katta struct - sekinlashtiruvchi omil, tezlashtiruvchi emas.

record - ma'lumot saqlash uchun #

record - asosan ma'lumot tashiydigan turlar uchun. U ko'p narsani o'zi yozib beradi:

CSHARP
var t1 = new Talaba("Husanboy", 25);
var t2 = new Talaba("Husanboy", 25);

Console.WriteLine(t1);
Console.WriteLine($"Teng-mi: {t1 == t2}");
Console.WriteLine($"Xesh bir xilmi: {t1.GetHashCode() == t2.GetHashCode()}");

record Talaba(string Ism, int Yosh);
Natija
Talaba { Ism = Husanboy, Yosh = 25 }
Teng-mi: True
Xesh bir xilmi: True

Bitta qator kod uchun biz quyidagilarni bepul oldik:

  • Konstruktor;
  • Ism va Yosh xossalari (init bilan);
  • Mazmunli ToString();
  • Qiymat bo'yicha tenglik (== va Equals);
  • Mos GetHashCode().

Xuddi shuni class bilan yozsangiz, natija boshqacha:

CSHARP
var t1 = new Talaba("Husanboy", 25);
var t2 = new Talaba("Husanboy", 25);

Console.WriteLine(t1);
Console.WriteLine($"Teng-mi: {t1 == t2}");

class Talaba(string ism, int yosh)
{
    public string Ism => ism;
    public int Yosh => yosh;
}
Natija
Talaba
Teng-mi: False

class da == havolalarni solishtiradi: bular ikki xil obyekt, demak teng emas. record da esa mazmun solishtiriladi.

Bu farq amalda qachon bilinadi

Tasavvur qiling, talabalar ro'yxatida qidiryapsiz:

CSHARP
var royxat = new List<Talaba> { new("Husanboy", 25) };

Console.WriteLine(royxat.Contains(new Talaba("Husanboy", 25)));

record Talaba(string Ism, int Yosh);
Natija
True

record bo'lgani uchun Contains topdi. class bo'lganida False chiqardi - garchi ma'lumot bir xil bo'lsa ham.

Xuddi shu narsa Dictionary kaliti, HashSet va Distinct() uchun ham amal qiladi.

with - nusxa olib, bir qismini o'zgartirish #

CSHARP
var asl = new Mahsulot("Non", 4000, "Non mahsulotlari");
var arzon = asl with { Narx = 3500 };

Console.WriteLine(asl);
Console.WriteLine(arzon);
Console.WriteLine($"Asl o'zgarmadi: {asl.Narx}");

record Mahsulot(string Nom, decimal Narx, string Turkum);
Natija
Mahsulot { Nom = Non, Narx = 4000, Turkum = Non mahsulotlari }
Mahsulot { Nom = Non, Narx = 3500, Turkum = Non mahsulotlari }
Asl o'zgarmadi: 4000

with yangi obyekt yaratadi va faqat ko'rsatilgan xossani o'zgartiradi. Qolgani nusxalanadi. Bu o'zgarmas ma'lumot bilan ishlashning qulay usuli.

record struct #

record ning qiymat turi ko'rinishi ham bor:

CSHARP
var p1 = new Pul(15000, "UZS");
var p2 = p1 with { Miqdor = 20000 };

Console.WriteLine($"{p1} / {p2}");
Console.WriteLine($"Teng-mi: {p1 == p2}");
Console.WriteLine($"Nusxa teng-mi: {p1 == p1 with { }}");

readonly record struct Pul(decimal Miqdor, string Valyuta);
Natija
Pul { Miqdor = 15000, Valyuta = UZS } / Pul { Miqdor = 20000, Valyuta = UZS }
Teng-mi: False
Nusxa teng-mi: True

readonly record struct - kichik, o'zgarmas qiymatlar uchun eng yaxshi tanlov: qiymat turi tezligi va record qulayligi birgalikda.

Uchtasini solishtirish #

classstructrecord
TurHavolaQiymatHavola (sukut bo'yicha)
TenglikHavola bo'yichaQiymat bo'yichaQiymat bo'yicha
ToString()Tur nomiMaydonlarMaydonlar
VorislikHaYo'qHa
with ifodasiYo'qYo'qHa
Asosiy maqsadXatti-harakatKichik qiymatMa'lumot
Qaysi birini tanlash Yangi tur kerak Asosan ma'lumot tashiydi, mazmuni bo'yicha solishtiriladi Kichik, o'zgarmas, juda ko'p yaratiladi Xatti-harakati bor, holati o'zgaradi record struct class Ikkilansangiz - class. U eng universal va hech qachon noto'g'ri tanlov emas.
Ikkilansangiz class dan boshlang - keyin o'zgartirish oson

enum - nomlangan qiymatlar to'plami #

CSHARP
Holat[] holatlar = [Holat.Yangi, Holat.Jarayonda, Holat.Yakunlangan];

foreach (Holat holat in holatlar)
{
    string izoh = holat switch
    {
        Holat.Yangi => "hali boshlanmagan",
        Holat.Jarayonda => "ishlanmoqda",
        Holat.Yakunlangan => "tugatilgan",
        _ => "noma'lum"
    };

    Console.WriteLine($"{holat,-12} ({(int)holat}) - {izoh}");
}

enum Holat
{
    Yangi,
    Jarayonda,
    Yakunlangan
}
Natija
Yangi        (0) - hali boshlanmagan
Jarayonda    (1) - ishlanmoqda
Yakunlangan  (2) - tugatilgan
enum satrdan ancha yaxshi

Holatni string bilan saqlash keng tarqalgan, lekin xavfli: "jarayonda", "Jarayonda" va "jarayon" - kompilyator uchun uchta turli qiymat va u xatoni topmaydi.

enum da esa noto'g'ri qiymat kompilyatsiya qilinmaydi. Bundan tashqari muharrir mumkin bo'lgan qiymatlarni o'zi taklif qiladi.

Amaliy topshiriq
  1. Nuqta ni struct qilib yozing va nusxa olinishini tekshiring.
  2. Xuddi shuni class qilib, farqni ko'ring.
  3. struct qachon mos kelishini uchta shart bilan yozing.
  4. record yarating va ikkita bir xil obyektni solishtiring.
  5. Xuddi shu record ni class qilib, == natijasini solishtiring.
  6. List.Contains ni record va class bilan sinab ko'ring.
  7. with ifodasi bilan nusxa olib, bitta xossani o'zgartiring.
  8. readonly record struct bilan pul turini yozing.
  9. Uchta holatli enum yarating va switch bilan ishlating.
  10. class, struct va record ni jadval ko'rinishida solishtiring.

Xulosa #

  • struct - qiymat turi: nusxalanadi, havola qilinmaydi.
  • struct faqat kichik, o'zgarmas va ko'p yaratiladigan qiymatlar uchun; aks holda class.
  • record ma'lumot turlari uchun: konstruktor, ToString, qiymat bo'yicha tenglik - hammasi bir qatorda.
  • record va class orasidagi farq Contains, Distinct, Dictionary kaliti kabi joylarda bilinadi.
  • with nusxa olib, bir qismini o'zgartiradi; asl obyekt o'zgarmaydi.
  • readonly record struct - kichik o'zgarmas qiymatlar uchun eng yaxshi tanlov.
  • enum holatni satr bilan saqlashdan xavfsizroq.
  • Ikkilansangiz - class.

Keyingi bo'limda null xavfsizligini o'rganamiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.