1. Giriş
Təsəvvür elə ki, alış-veriş siyahısı aparırsan. Bu gün 3 məhsul almalısan, sabah — 10, birisi gün isə cəmi bir dənə. Əgər massiv istifadə etsəydin, hər dəfə konkret məhsul sayına uyğun yeni massiv yaratmalı olardın. Ya da "birdən lazım olar" deyə çox böyük massiv yaradıb, bir sürü boş hüceyrə "daşımalı" olardın. Səmərəli səslənmir, düzdür?
İndi təsəvvür elə ki, sənin sehrli çantan var, ora nə qədər əşya qoysan, özü böyüyür, çıxarsan, kiçilir. Əvvəlcədən neçə əşya qoyacağını bilməyə ehtiyac yoxdur. Sadəcə qoyursan, çanta özü uyğunlaşır. Bax, proqramlaşdırmada C#-da List<T> məhz budur!
List<T> — müəyyən tipdə elementlər ardıcıllığını saxlamağa imkan verən ümumiləşdirilmiş kolleksiyadır. Əsas söz — "dinamik". Massivlərdən fərqli olaraq, List<T> proqram işləyərkən öz ölçüsünü dəyişə bilir. O, daxili tutumunu özü idarə edir, lazım olanda artırır.
List<T>-də T hərfi nə deməkdir? Bu, tip parametri adlanır. List yaradanda, T yerinə hansı tipdə məlumat saxlayacağını göstərirsən. Məsələn, List<int> yalnız tam ədədlər, List<string> yalnız sətirlər, List<double> isə yalnız onluq ədədlər saxlayacaq. Bu, təsadüfən portağal siyahısına alma əlavə etməyinə imkan vermir, kodunun sabitliyi və proqnozlaşdırılması üçün vacibdir.
Bunu niyə istifadə edirik?
Real layihələrdə çox vaxt əvvəlcədən neçə element olacağını bilmirsən. Məsələn:
- Sayta daxil olan istifadəçilərin siyahısı.
- Onlayn mağazanın səbətindəki məhsulların siyahısı.
- Sorğuya görə axtarış nəticələrinin siyahısı.
- Planlaşdırıcıda tapşırıqların siyahısı — indi məhz bunu hazırlayacağıq.
Bütün bu hallarda elementlərin sayı dəyişə bilər və List<T> bizim əvəzolunmaz köməkçimiz olur.
List<T>-in əsas metodları
| Metod | Təsviri | Nümunə |
|---|---|---|
|
Siyahının sonuna element əlavə et | |
|
Göstərilən mövqeyə əlavə et | |
|
Elementin ilk tapılanını sil | |
|
Elementi indeksə görə sil | |
|
Siyahını tam təmizlə | |
|
Siyahıda element var, ya yox — yoxla | |
|
Elementin ilk tapıldığı indeks | |
|
Siyahıdakı elementlərin sayı | |
|
Daxili buffer-in tutumu | |
2. Siyahı (List<T>) yaratmaq
Keçək praktikaya! Təsəvvür elə ki, sadə tapşırıq meneceri yaratmaq qərarına gəlmişik. Bizə siyahı lazımdır ki, ora işlərimizi əlavə edək.
Yeni List<T> yaratmaq üçün new operatorundan istifadə edirik, digər obyektlərdə olduğu kimi.
List necə elan və yaradılır
Siyahı yaratmaq sintaksisi massivə bənzəyir, sadəcə kvadrat mötərizə yerinə kəskin mötərizə:
using System.Collections.Generic;
List<int> numbers = new List<int>();
Ətraflı bilmək istəyənlər üçün şərhlər:
- List<int> — tam ədədlər siyahısıdır (int). int yerinə istənilən tip yaza bilərsən: string, double, öz class-ın və s.
- Yaradandan sonra siyahı boşdur — uzunluğu 0-dır.
Nümunə: tətbiqimizin ilk addımı
Tutaq ki, tətbiqimizdə istifadəçi ad və yaş daxil edirdi (ilk dərslərdən yadındadır). İndi isə bir neçə ad saxlamaq üçün siyahı əlavə edək ki, sonra onlarla işləyə bilək.
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<string> names = new List<string>();
Console.WriteLine("Üç ad daxil edin:");
for (int i = 0; i < 3; i++)
{
string name = Console.ReadLine();
names.Add(name);
}
Console.WriteLine("Daxil etdikləriniz:");
foreach (string n in names)
{
Console.WriteLine(n);
}
}
}
Diqqət et Add()-ə. Məhz bu metod siyahıya yeni elementlər əlavə edir. Yəni — onu dinamik edir!
Siyahını dərhal elementlərlə yaratmaq olar!
List<string> planets = new List<string> { "Merkuri", "Venera", "Yer" };
Çox rahatdır, əgər "start heyəti" bilirsənsə. Bu sintaksis testlərdə və sabit məlumatların ilkinizasiya üçün tez-tez istifadə olunur.
3. List<T> ilə əsas əməliyyatlar
Hələ trüklərə keçməmiş, gəlin siyahının "əlifbasını" öyrənək.
Element əlavə etmək: Add()
Add() metodunu istifadə etmək — yeni əşyanı rəfə qoymaq kimidir:
List<int> numbers = new List<int>();
numbers.Add(42);
numbers.Add(100);
İndi içində: [42, 100]
Elementlərin sayını almaq: Count
Massivdən fərqli olaraq, siyahıda bu xüsusiyyət Length yox, Count adlanır:
int count = numbers.Count; // 2 qaytaracaq
Yadda saxla: siyahılarda Count istifadə olunur, massiv və sətirlərdə isə Length. Eyni məqsəd üçün fərqli xüsusiyyətlərdir.
Elementlərə indekslə müraciət
İki üsul var, mahiyyətcə eynidir:
int first = numbers[0]; // 42
numbers[1] = 200; // 100-ü 200 ilə əvəz etdik
Vacibdir: İndeksləmə, massivlərdə olduğu kimi, sıfırdan başlayır. Cəmi üç elementin varsa, numbers[3]-ə müraciət etmə!
Siyahı elementlərini dövr etmək
for və ya foreach dövründən istifadə edə bilərsən:
// for ilə — indeks lazımdırsa
for (int i = 0; i < numbers.Count; i++)
{
Console.WriteLine(numbers[i]);
}
// foreach ilə — indeks lazım deyilsə
foreach (int number in numbers)
{
Console.WriteLine(number);
}
foreach adətən daha rahat və başadüşüləndir, xüsusən böyük kolleksiyalarda.
Amma onunla kolleksiyanın elementlərini indekslə dəyişə və ya break ilə dövrü vaxtından əvvəl dayandıra bilməzsən, əlavə konstruksiyalar istifadə etməsən.
Elementi indeksə görə əlavə etmək: Insert()
Insert() metodu, əgər elementi siyahının sonuna yox, istənilən yerə əlavə etmək istəsən, istifadə olunur. Məsələn, ikinci yerə:
numbers.Insert(1, 55); // 55-i indeks 1-ə əlavə edəcək
İndi numbers: [42, 55, 200]
Elementləri silmək
Siyahıdan silmək əlavə etmək qədər asandır:
numbers.Remove(55); // 55-in İLK tapılanını siləcək
numbers.RemoveAt(0); // 0 indeksli elementi siləcək
numbers.Clear(); // Siyahını tam təmizləyir
Silinmənin nüansları:
- Remove ilə mövcud olmayan dəyəri silsən, heç nə baş verməyəcək: siyahı dəyişməyəcək, səhv almayacaqsan.
- Clear()-dan sonra siyahı yenə boşdur.
4. Faydalı nüanslar
List<T> necə böyüyür
List<T>-ə element əlavə edəndə, o, hər dəfə bir az böyümür. Əvəzində List<T> əvvəlcədən ehtiyatla yaddaş ayırır (daxili tutum — Capacity).
Elementlərin sayı tutumu keçəndə, siyahı daha böyük yaddaş bloku ayırır (adətən 2 dəfə böyük) və bütün köhnə dəyərləri ora köçürür:
Element əlavə edirik → yerləşdi → yerləşdi → yerləşdi →
Yeni element yerləşmir → böyük massiv yaradılır → məlumatlar köçürülür → davam edirik
Bu, elementləri daha tez əlavə etməyə imkan verir, çünki yaddaş hər Add-da yox, ara-sıra yenidən bölüşdürülür.
var list = new List<int>(); // Capacity = 0
list.Add(1); // Capacity = 4
list.Add(2); // Capacity = 4
list.Add(3); // Capacity = 4
list.Add(4); // Capacity = 4
list.Add(5); // Capacity = 8 (böyüdü!)
Capacity və Count: fərq nədir?
- Count — siyahıya əlavə olunan elementlərin sayı.
- Capacity — elementləri saxlayan daxili massiv ölçüsü.
List<int> nums = new List<int>();
Console.WriteLine(nums.Count); // 0
Console.WriteLine(nums.Capacity); // Adətən 0 və ya kiçik ölçü
nums.Add(123);
Console.WriteLine(nums.Count); // 1
Console.WriteLine(nums.Capacity); // İndi Count-dan çox ola bilər
nums.Capacity = 1000; // Əgər çox element olacaqsa, Capacity-ni əvvəlcədən artıra bilərsən
Əksər proqramçılar yalnız Count-dan istifadə edir, amma performansa həssas tətbiqlər yazırsansa (məsələn, oyunlar və ya data analizi), Capacity-ni incə tənzimləmək faydalı ola bilər.
5. Nümunə
Kiçik tətbiqimizi inkişaf etdiririk — indi istifadəçi sevdiyi ədədləri əlavə edə, sonra siyahı ilə işləyə: əlavə, silmək, göstərmək və təmizləmək.
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<int> favoriteNumbers = new List<int>();
Console.WriteLine("Sevdiyiniz ədədləri daxil edin (hər sətrə bir dənə, 0 — bitir):");
while (true)
{
int num = int.Parse(Console.ReadLine());
if (num == 0) break;
favoriteNumbers.Add(num);
}
Console.WriteLine("Sevdiyiniz ədədlər:");
foreach (int n in favoriteNumbers)
{
Console.Write(n + " ");
}
Console.WriteLine("\nBirinci ədədi silmək istəyirsiniz? (y/n)");
if (Console.ReadLine().ToLower() == "y")
{
favoriteNumbers.RemoveAt(0);
}
Console.WriteLine("İndi siyahınız:");
foreach (int n in favoriteNumbers)
{
Console.Write(n + " ");
}
}
}
Qeyd: Burada int.Parse istifadə edirik. Real layihələrdə istifadəçi səhvlərinə görə proqramın "çöküb" getməməsi üçün həmişə int.TryParse ilə yoxlamaq daha yaxşıdır.
6. Başlanğıc üçün tipik səhvlər və "tələ"lər
Çox yayılmış ssenari: 0-dan List.Count-a qədər dövr yazırsan, amma dövr zamanı (məsələn, foreach-də) siyahını dəyişirsən (əlavə və ya silmə). Bunu etmə! Proqramçılar buna "dövr zamanı kolleksiyanı dəyişmək" deyir. Çox vaxt dərhal InvalidOperationException tipli istisna alırsan.
Pis kod nümunəsi:
foreach (int n in numbers)
{
if (n < 0)
numbers.Remove(n); // BUM! Runtime error.
}
Düzgün: ya silmək üçün indeksləri/elementləri ayrıca siyahıda topla, ya da for dövrünü tərsinə istifadə et.
GO TO FULL VERSION