3-bo‘lim

Turlar va o'zgaruvchilar

Qiymat va havola turlari, butun va kasr sonlar, decimal, var va const, turlarni aylantirish, TryParse va madaniyatga bog'liq formatlash.

🕑 19 daqiqa o‘qish 📄 1 082 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. O'zgaruvchi e'lon qilish
  2. Asosiy turlar
  3. Qiymat va havola turlari
  4. var - turni kompilyator aniqlaydi
  5. const va readonly
  6. Kasr sonlar va aniqlik
  7. Turlarni aylantirish
  8. Yo'qotishsiz - o'zi bo'ladi
  9. Yo'qotish bilan - oshkora yozish shart
  10. Satrdan songa
  11. Madaniyat va kasr ajratuvchisi
  12. Xulosa

C# qat'iy turlangan til: har bir o'zgaruvchining turi bor va u o'zgarmaydi. Bu ko'proq yozishni talab qiladi, lekin xatolarning katta qismini dastur ishga tushmasdan oldin topadi.

O'zgaruvchi e'lon qilish #

CSHARP
int yosh = 25;
string ism = "Husanboy";
bool talabami = true;

Console.WriteLine($"{ism}, {yosh} yosh, talaba: {talabami}");
Natija
Husanboy, 25 yosh, talaba: True

Diqqat: bool qiymati True deb bosh harf bilan chiqdi. Bu C# ning Boolean.ToString() qoidasi - kodda esa true deb kichik harf bilan yoziladi.

Asosiy turlar #

TurHajmiDiapazon yoki maqsad
int4 bayt-2 mlrd dan +2 mlrd gacha - odatiy tanlov
long8 baytJuda katta butun sonlar
short, byte2 va 1 baytXotira tejash kerak bo'lganda
double8 baytKasr sonlar - odatiy tanlov
float4 baytKamroq aniqlik, grafikada
decimal16 baytPul - aniq o'nlik hisob
bool1 bayttrue yoki false
char2 baytBitta belgi: 'A'
string-Matn

Chegaralarni o'zingiz ko'rishingiz mumkin:

CSHARP
Console.WriteLine($"int:   {int.MinValue} .. {int.MaxValue}");
Console.WriteLine($"long:  {long.MinValue} .. {long.MaxValue}");
Console.WriteLine($"byte:  {byte.MinValue} .. {byte.MaxValue}");
Natija
int:   -2147483648 .. 2147483647
long:  -9223372036854775808 .. 9223372036854775807
byte:  0 .. 255

Qiymat va havola turlari #

Bu C# dagi eng muhim ajratish. Unga tushunmasdan keyingi bo'limlarni o'zlashtirib bo'lmaydi.

Xotirada qanday saqlanadi Qiymat turi (int, double, struct) int a = 5; int b = a; b = 9; a 5 b 9 Nusxa olinadi - ikki mustaqil katak a = 5, b = 9 b ni o'zgartirish a ga ta'sir qilmaydi Havola turi (class, array, string) int[] x = [5]; int[] y = x; y[0] = 9; x y bitta massiv [9] x[0] = 9, y[0] = 9 Ikkalasi bitta obyektga ishora qiladi
Qiymat turi nusxalanadi, havola turi esa faqat manzili nusxalanadi

Buni amalda ko'ramiz:

CSHARP
int a = 5;
int b = a;
b = 9;
Console.WriteLine($"Qiymat turi:  a = {a}, b = {b}");

int[] x = [5];
int[] y = x;
y[0] = 9;
Console.WriteLine($"Havola turi:  x[0] = {x[0]}, y[0] = {y[0]}");
Natija
Qiymat turi:  a = 5, b = 9
Havola turi:  x[0] = 9, y[0] = 9
Qiymat turlariHavola turlari
int, double, bool, charclass bilan yaratilganlar
struct (11-bo'lim)string, massivlar, List<T>
enumrecord (11-bo'lim)
Nusxa olinadiManzil nusxalanadi
string havola turi, lekin o'zini boshqacha tutadi

string texnik jihatdan havola turi, lekin u o'zgarmas (immutable): mavjud satrni tahrirlab bo'lmaydi, har bir amal yangi satr yaratadi.

Shuning uchun satrlarda yuqoridagi kutilmagan hodisa yuz bermaydi - ular xuddi qiymat turlaridek tuyuladi. Buni keyingi bo'limda batafsil ko'ramiz.

var - turni kompilyator aniqlaydi #

CSHARP
var yosh = 25;              // int
var narx = 12.5;            // double
var ism = "Malika";         // string
var raqamlar = new[] { 1, 2, 3 };   // int[]

Console.WriteLine($"{ism}: {yosh}");
Console.WriteLine($"Massiv uzunligi: {raqamlar.Length}");
Console.WriteLine($"narx turi: {narx.GetType().Name}");
Natija
Malika: 25
Massiv uzunligi: 3
narx turi: Double

var - "turi yo'q" degani emas. Tur baribir qat'iy belgilanadi, uni shunchaki kompilyator o'ng tomondagi qiymatdan aniqlaydi. Keyin uni o'zgartirib bo'lmaydi.

var ni qachon ishlatish kerak

Qoida oddiy: o'ng tomonga qarab tur ko'rinib tursa - var yozing.

CSHARP
var mijoz = new Mijoz();                  // aniq
var royxat = new List<string>();          // aniq
var natija = HisoblaNimadir();            // NOANIQ - tur ko'rinmaydi

Oxirgi holatda to'liq turni yozgan ma'qul: keyin kod o'qiyotgan odam (yoki olti oydan keyingi siz) metodga kirmasdan turni bilishi kerak.

const va readonly #

CSHARP
const double PiTaxminan = 3.14159;
const string Maktab = "14-maktab";

Console.WriteLine($"{Maktab}, aylana uzunligi: {2 * PiTaxminan * 5}");
Natija
14-maktab, aylana uzunligi: 31.4159

const qiymati kompilyatsiya paytida ma'lum bo'lishi kerak va keyin hech qachon o'zgarmaydi.

Kasr sonlar va aniqlik #

Bu barcha tillarda uchraydigan tuzoq va C# ham istisno emas:

CSHARP
double a = 0.1;
double b = 0.2;

Console.WriteLine(a + b == 0.3);
Console.WriteLine((a + b).ToString("R"));
Natija
False
0.30000000000000004

0.1 + 0.2 aniq 0.3 bermaydi. Sababi: double sonni ikkilik kasrda saqlaydi va 0.1 ni ikkilikda aniq ifodalab bo'lmaydi - xuddi 1/3 ni o'nlik kasrda aniq yozib bo'lmagani kabi.

Pul uchun hech qachon double ishlatmang

Pul hisobida double xatosi to'planib, haqiqiy zararga aylanadi. Buning uchun decimal bor - u sonni o'nlik asosda saqlaydi:

CSHARP
decimal a = 0.1m;
decimal b = 0.2m;

Console.WriteLine(a + b == 0.3m);
Console.WriteLine(a + b);
Natija
True
0.3

Oxiridagi m harfi majburiy - usiz kompilyator sonni double deb o'qiydi va decimal ga bermaydi.

Qoida: pul va moliyaviy hisob - decimal, o'lchov va ilmiy hisob - double.

Turlarni aylantirish #

Yo'qotishsiz - o'zi bo'ladi #

CSHARP
int kichik = 42;
long katta = kichik;      // int -> long, muammosiz
double kasr = kichik;     // int -> double, muammosiz

Console.WriteLine($"{katta} va {kasr}");
Natija
42 va 42

Yo'qotish bilan - oshkora yozish shart #

CSHARP
double narx = 19.99;
int butun = (int)narx;        // kasr qismi tashlanadi

Console.WriteLine($"{narx.ToString("R")} -> {butun}");
Console.WriteLine($"Yaxlitlash: {Math.Round(narx)}");
Natija
19.99 -> 19
Yaxlitlash: 20
(int) yaxlitlamaydi - kesib tashlaydi

Yuqorida (int)19.99 natijasi 19 bo'ldi, 20 emas. Oshkora aylantirish kasr qismini shunchaki tashlab yuboradi.

Bu narx hisobida jiddiy xato manbai: 1000 ta mahsulotda har biridan bir tiyin yo'qotilsa, yig'indi sezilarli bo'ladi.

Yaxlitlash kerak bo'lsa Math.Round ishlating. E'tibor bering: Math.Round(0.5) natijasi 0 - C# sukut bo'yicha juft songa yaxlitlaydi (bankir yaxlitlashi). Odatdagi yaxlitlash uchun Math.Round(x, MidpointRounding.AwayFromZero) yozing.

Buni ham tekshirib ko'raylik:

CSHARP
Console.WriteLine($"Math.Round(0.5) = {Math.Round(0.5)}");
Console.WriteLine($"Math.Round(1.5) = {Math.Round(1.5)}");
Console.WriteLine($"Math.Round(2.5) = {Math.Round(2.5)}");
Console.WriteLine(
    $"AwayFromZero(0.5) = {Math.Round(0.5, MidpointRounding.AwayFromZero)}");
Natija
Math.Round(0.5) = 0
Math.Round(1.5) = 2
Math.Round(2.5) = 2
AwayFromZero(0.5) = 1

0.5 va 2.5 ikkalasi ham 2 ga yaxlitlandi - chunki eng yaqin juft son tanlanadi.

Satrdan songa #

Foydalanuvchi kiritgan ma'lumot har doim satr bo'ladi. Uni songa aylantirishning uch usuli bor:

CSHARP
// 1. Parse - xato bo'lsa istisno tashlaydi
int a = int.Parse("42");

// 2. TryParse - xato bo'lsa false qaytaradi
bool muvaffaqiyat = int.TryParse("abc", out int b);

// 3. Convert - null ni ham qabul qiladi
int c = Convert.ToInt32("7");

Console.WriteLine($"Parse: {a}");
Console.WriteLine($"TryParse: natija={muvaffaqiyat}, qiymat={b}");
Console.WriteLine($"Convert: {c}");
Natija
Parse: 42
TryParse: natija=False, qiymat=0
Convert: 7
O'zgaruvchi nomida apostrof ishlatib bo'lmaydi

Bu o'zbek tilida yozadigan dasturchi birinchi kunlardayoq uchraydigan to'siq. Tabiiy ko'ringan nom kompilyatsiya qilinmaydi:

CSHARP
bool bo'ldi = true;      // XATO

Kompilyator ' belgisini belgi literali boshlanishi deb o'qiydi va quyidagi xatoni beradi:

Natija
error CS1012: Too many characters in character literal
error CS1010: Newline in constant

Uchta yechim bor:

YechimMisolBaho
Apostrofsiz yozishboldi, royxat, togriTavsiya etiladi
Sinonim tanlashnatija, jadval, jamiEng yaxshisi
Haqiqiy tutuq belgisi (U+02BB)boʻldiIshlaydi, lekin terish qiyin

Uchinchi variant haqiqatan kompilyatsiya qilinadi, chunki ʻ Unicode tasnifida harf hisoblanadi. Lekin uni klaviaturadan terish noqulay, shuning uchun bu darslikda apostrofsiz nomlar ishlatiladi.

Har doim TryParse ni tanlang

Foydalanuvchi ma'lumoti bilan ishlaganda Parse xavfli: bitta noto'g'ri belgi butun dasturni to'xtatadi.

TryParse esa false qaytaradi va dastur nazorat sizda qoladi:

CSHARP
string kiritilgan = "yigirma besh";

if (int.TryParse(kiritilgan, out int yosh))
{
    Console.WriteLine($"Yosh: {yosh}");
}
else
{
    Console.WriteLine("Iltimos, raqam kiriting");
}
Natija
Iltimos, raqam kiriting

out kalit so'zi metodga "natijani shu o'zgaruvchiga yozib qo'y" deydi. U haqda 8-bo'limda gaplashamiz.

Madaniyat va kasr ajratuvchisi #

Bu C# da eng ko'p vaqt yo'qotadigan tuzoqlardan biri.

CSHARP
using System.Globalization;

double narx = 1234.5;
var ruRU = CultureInfo.GetCultureInfo("ru-RU");

Console.WriteLine(narx.ToString(CultureInfo.InvariantCulture));
Console.WriteLine(narx.ToString(ruRU));

// Guruh ajratuvchisi qaysi belgi ekanini aniq ko'ramiz
var inv = CultureInfo.InvariantCulture;
string invAjratuvchi = inv.NumberFormat.NumberGroupSeparator;
string ruAjratuvchi = ruRU.NumberFormat.NumberGroupSeparator;

Console.WriteLine(
    $"invariant guruh ajratuvchisi: U+{(int)invAjratuvchi[0]:X4}");
Console.WriteLine(
    $"ru-RU guruh ajratuvchisi:     U+{(int)ruAjratuvchi[0]:X4}");
Natija
1234.5
1234,5
invariant guruh ajratuvchisi: U+002C
ru-RU guruh ajratuvchisi:     U+00A0

Bir xil son, ikki xil ko'rinish. Kasr ajratuvchisi operatsion tizim sozlamasiga bog'liq: rus yoki o'zbek tiliga sozlangan Windows'da nuqta o'rniga vergul chiqadi.

Guruh ajratuvchisi oddiy bo'shliq emas

Yuqoridagi chiqishga diqqat qiling: ru-RU madaniyatida minglarni ajratuvchi belgi U+00A0 - ya'ni uzilmas bo'shliq, oddiy bo'shliq (U+0020) emas.

Bu ko'zga ko'rinmaydigan, lekin juda ko'p vaqt yeydigan tuzoq. Faylda 1 234,50 deb yozilgan sonni oddiy bo'shliqni olib tashlab tahlil qilmoqchi bo'lsangiz, kod ishlamaydi - chunki u yerda boshqa belgi turadi.

Aynan shuning uchun keyingi qoida mavjud.

Fayl va tarmoqqa yozganda har doim InvariantCulture

Muammo shunda: 1234,5 deb saqlangan sonni boshqa kompyuter int.Parse bilan o'qiganda butunlay boshqa qiymat chiqishi yoki xato berishi mumkin.

Qoida:

  • Ekranga chiqarganda - foydalanuvchi madaniyati (sukut bo'yicha shunday);
  • Faylga, bazaga, JSON ga yoki tarmoqqa - har doim CultureInfo.InvariantCulture.

Bu darslikdagi misollarda sonlar aynan shu sababdan InvariantCulture bilan chiqariladi - shunda natija sizning kompyuteringizda ham xuddi shunday bo'ladi.

Amaliy topshiriq
  1. int, double va decimal uchun bittadan o'zgaruvchi e'lon qiling.
  2. int.MaxValue ga 1 qo'shib, nima bo'lishini ko'ring.
  3. Qiymat va havola turi farqini massiv misolida takrorlang.
  4. var bilan besh xil turdagi o'zgaruvchi yarating va GetType().Name bilan tekshiring.
  5. 0.1 + 0.2 == 0.3 ni double va decimal da solishtiring.
  6. (int)9.99 va Math.Round(9.99) natijalarini solishtiring.
  7. Math.Round(3.5) va Math.Round(4.5) natijalarini tushuntiring.
  8. int.TryParse yordamida foydalanuvchi kiritgan matnni tekshiruvchi kod yozing.
  9. Bitta sonni uchta turli madaniyatda chiqaring.
  10. Nega pul uchun decimal kerakligini bir abzatsda yozing.

Xulosa #

  • C# qat'iy turlangan: har bir o'zgaruvchining o'zgarmas turi bor.
  • Qiymat turlari nusxalanadi, havola turlari da faqat manzil nusxalanadi.
  • var turni yo'q qilmaydi - uni kompilyator o'ng tomondan aniqlaydi.
  • double kasr sonlarni aniq saqlamaydi: 0.1 + 0.2 != 0.3.
  • Pul uchun decimal va son oxiriga m harfi.
  • (int) yaxlitlamaydi, kesadi; Math.Round sukut bo'yicha juft songa yaxlitlaydi.
  • Foydalanuvchi ma'lumoti uchun TryParse, Parse emas.
  • Faylga va tarmoqqa yozganda har doim InvariantCulture.

Keyingi bo'limda satrlar bilan ishlashni 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.