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.
Ushbu bo‘lim mundarijasi
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 #
int yosh = 25;
string ism = "Husanboy";
bool talabami = true;
Console.WriteLine($"{ism}, {yosh} yosh, talaba: {talabami}");
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 #
| Tur | Hajmi | Diapazon yoki maqsad |
|---|---|---|
int | 4 bayt | -2 mlrd dan +2 mlrd gacha - odatiy tanlov |
long | 8 bayt | Juda katta butun sonlar |
short, byte | 2 va 1 bayt | Xotira tejash kerak bo'lganda |
double | 8 bayt | Kasr sonlar - odatiy tanlov |
float | 4 bayt | Kamroq aniqlik, grafikada |
decimal | 16 bayt | Pul - aniq o'nlik hisob |
bool | 1 bayt | true yoki false |
char | 2 bayt | Bitta belgi: 'A' |
string | - | Matn |
Chegaralarni o'zingiz ko'rishingiz mumkin:
Console.WriteLine($"int: {int.MinValue} .. {int.MaxValue}");
Console.WriteLine($"long: {long.MinValue} .. {long.MaxValue}");
Console.WriteLine($"byte: {byte.MinValue} .. {byte.MaxValue}");
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.
Buni amalda ko'ramiz:
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]}");
Qiymat turi: a = 5, b = 9
Havola turi: x[0] = 9, y[0] = 9
| Qiymat turlari | Havola turlari |
|---|---|
int, double, bool, char | class bilan yaratilganlar |
struct (11-bo'lim) | string, massivlar, List<T> |
enum | record (11-bo'lim) |
| Nusxa olinadi | Manzil nusxalanadi |
string havola turi, lekin o'zini boshqacha tutadistring 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 #
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}");
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 kerakQoida oddiy: o'ng tomonga qarab tur ko'rinib tursa - var yozing.
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 #
const double PiTaxminan = 3.14159;
const string Maktab = "14-maktab";
Console.WriteLine($"{Maktab}, aylana uzunligi: {2 * PiTaxminan * 5}");
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:
double a = 0.1;
double b = 0.2;
Console.WriteLine(a + b == 0.3);
Console.WriteLine((a + b).ToString("R"));
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.
double ishlatmangPul hisobida double xatosi to'planib, haqiqiy zararga aylanadi.
Buning uchun decimal bor - u sonni o'nlik asosda saqlaydi:
decimal a = 0.1m;
decimal b = 0.2m;
Console.WriteLine(a + b == 0.3m);
Console.WriteLine(a + b);
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 #
int kichik = 42;
long katta = kichik; // int -> long, muammosiz
double kasr = kichik; // int -> double, muammosiz
Console.WriteLine($"{katta} va {kasr}");
42 va 42
Yo'qotish bilan - oshkora yozish shart #
double narx = 19.99;
int butun = (int)narx; // kasr qismi tashlanadi
Console.WriteLine($"{narx.ToString("R")} -> {butun}");
Console.WriteLine($"Yaxlitlash: {Math.Round(narx)}");
19.99 -> 19
Yaxlitlash: 20
(int) yaxlitlamaydi - kesib tashlaydiYuqorida (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:
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)}");
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:
// 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}");
Parse: 42
TryParse: natija=False, qiymat=0
Convert: 7
Bu o'zbek tilida yozadigan dasturchi birinchi kunlardayoq uchraydigan to'siq. Tabiiy ko'ringan nom kompilyatsiya qilinmaydi:
bool bo'ldi = true; // XATO
Kompilyator ' belgisini belgi literali boshlanishi deb o'qiydi
va quyidagi xatoni beradi:
error CS1012: Too many characters in character literal
error CS1010: Newline in constant
Uchta yechim bor:
| Yechim | Misol | Baho |
|---|---|---|
| Apostrofsiz yozish | boldi, royxat, togri | Tavsiya etiladi |
| Sinonim tanlash | natija, jadval, jami | Eng yaxshisi |
| Haqiqiy tutuq belgisi (U+02BB) | boʻldi | Ishlaydi, 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.
TryParse ni tanlangFoydalanuvchi ma'lumoti bilan ishlaganda Parse xavfli: bitta noto'g'ri
belgi butun dasturni to'xtatadi.
TryParse esa false qaytaradi va dastur nazorat sizda qoladi:
string kiritilgan = "yigirma besh";
if (int.TryParse(kiritilgan, out int yosh))
{
Console.WriteLine($"Yosh: {yosh}");
}
else
{
Console.WriteLine("Iltimos, raqam kiriting");
}
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.
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}");
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.
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.
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.
int,doublevadecimaluchun bittadan o'zgaruvchi e'lon qiling.int.MaxValuega 1 qo'shib, nima bo'lishini ko'ring.- Qiymat va havola turi farqini massiv misolida takrorlang.
varbilan besh xil turdagi o'zgaruvchi yarating vaGetType().Namebilan tekshiring.0.1 + 0.2 == 0.3nidoublevadecimalda solishtiring.(int)9.99vaMath.Round(9.99)natijalarini solishtiring.Math.Round(3.5)vaMath.Round(4.5)natijalarini tushuntiring.int.TryParseyordamida foydalanuvchi kiritgan matnni tekshiruvchi kod yozing.- Bitta sonni uchta turli madaniyatda chiqaring.
- Nega pul uchun
decimalkerakligini 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.
varturni yo'q qilmaydi - uni kompilyator o'ng tomondan aniqlaydi.doublekasr sonlarni aniq saqlamaydi:0.1 + 0.2 != 0.3.- Pul uchun
decimalva son oxirigamharfi. (int)yaxlitlamaydi, kesadi;Math.Roundsukut bo'yicha juft songa yaxlitlaydi.- Foydalanuvchi ma'lumoti uchun
TryParse,Parseemas. - Faylga va tarmoqqa yozganda har doim
InvariantCulture.
Keyingi bo'limda satrlar bilan ishlashni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
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.