A Listák a tömbökhöz hasonló adatszerkezetek, amik egy típusból tartalmaznak több példányt úgy, hogy a lista egyes elemei, index-ükön (sorszámukon) keresztül érhető el.
Fő különbsége a listának a tömbökhöz képest, hogy sokkal dinamikusabbak . A Listák nem fix hosszúságúak, azaz hozzáadhatunk, elemet és törlhetünk is belőle.
A C#-ban listákat List<T>
típus írja le, ahol T
az adott lista elemeinek típusát jelöli.
Ez az osztály a System.Collections.Generic
névtérben található, szóval a fájl elején fel kell tüntetni, hogy használni szeretnénk azt:
using System.Collections.Generic;
Listák Létrehozása
Egy lista létrehozásánál nem kell megadni a darabszámot. Például egy int
típusú lista létrehozásához a következő kódot kell használni:
List<int> myList = new List<int>(); // Létrehozuk egy üres listát.
Azokat a típusokat, amik létrehozásakor meg kell adni egy egyéb típust (relációsjelek közt) generikus típusoknak nevezzük. A generikus típusok egy általános megoldást nyújtanak egy széleskörű problémára. (A listák esetében ez adott típusú sorozatok dinamikus tárolása.) A megoldás általánosan van megoldva egy ismeretlen <T>
generikus típusra, viszont amikor egy konkrét objektumot létrehozunk, akkor definiálnunk kell, hogy melyik típus lesz ez a T, melyik típusból hozunk létre listát.
A fenti módon üres listát hozunk létre, de ahogy az tömbök esetén történt, most is lehetőségünk van előre feltölteni őket.
List<int> myIntList1 = new List<int>(){ 1, 3, 42 };
List<int> myIntList2 = new List<int>{ 1, 3, 42 }; // Üres paraméterlista itt elhagyható
List<string> friends =
new List<string>{ "Rachel", "Monica", "Phoebe", "Joey", "Chandler", "Ross" };
A C# 9-tól kezdődően (Unity 2021.2) a new
kulcsszó után a típus kiírása elhagyható, ha az a deklaráció alapján egyértelmű a fordító számára. Tehát:
List<int> myListA = new List<int> {1, 2}; // ✔️ Ez így jó
// Üres paraméterlista itt elhagyható
List<int> myListB = new () {1, 2}; // ✔️ És ez is ugyanúgy jó
// Üres paraméterlista NEM elhagyható
var myListC = new List<int>{1, 2}; // ✔️ Ez szintúgy működik
var myListD = new () {1, 2}; // 🛑 ERROR! A fordító nem tudja, milyen típus
Indexelés
Egy lista elemeihez hozzáférhetünk indexükön keresztül ugyanúgy, ahogy az a tömbök esetében történt. Például egy lista első azaz 0-ás indexű eleméhez az alábbi kóddal férhetünk hozzá:
int firstElement = myList[0]; // Első elem lekérdezése
myList[0] = 33; // Első elem módosítása
Lista hosszát a Count
property-vel tudjuk lekérdezni:
int count = myList.Count;
Ezek szerint a lista utolsó elemét a következőképp érjük el:
int firstElement = myList[myList.Count-1]; // Utolsó elem lekérdezése
myList[myList.Count-1] = -93; // Utolsó elem módosítása
Hozzáadás, törlés
Az új elemek hozzáadásához a Add()
metódust kell használni. Ekkor a lista végére tesszük az új elemet. Ha más indexre szeretnénk beszúrni, akkor az Insert()
metódus használjuk.
Mindekét esetben paraméterben kell megadni az új elemet, az insert esetén azt az indexet is ahova be akarunk illeszteni egy új elemet:
List<string> myList = new(); // Létrehozuk egy üres listát.
myList.Add("A"); // { "A" }
myList.Add("B"); // { "A", "B" }
myList.Add("C"); // { "A", "B", "C" }
myList.Insert(1, "D"); // { "A", "D", "B", "C" }
myList.Insert(0, "E"); // { "E", "A", "D", "B", "C" }
myList.Insert(5, "F"); // { "E", "A", "D", "B", "C", "F" }
Az elemeket el is tudjuk távolítani egy listából a RemoveAt()
metódussal, ami a törlendő elem indexét várja paraméterként, valamint a Remove()
metódussal ami pedig a törlendő elemet magát.
List<float> myFloats = new (){ 1.1f, 2.2f, 3.3f, 4.4f, 5.5f };
myFloats .RemoveAt(0); // Eltávolítjuk az első elemet
myFloats .RemoveAt(myFloats.Count-1); // Eltávolítjuk az utolsó elemet
List<string> fellowship = new() {"Frodo", "Sam", "Merry", "Pippin", "Gandalf",
"Aragorn", "Legolas", "Gimli", "Boromir"};
fellowship.Remove("Boromir"); // Egy konkrét elem kivétele
Ha egy listából kiveszünk egy elemet vagy beillesztünk egy újat, akkor az azt követő utána következő elemek átindexelődnek.
List<string> avengers = new (){ "Ironman", "Capt. America", "Thor", "Hulk" };
// Indexek: 0 1 2 3
avengers.Remove("Ironman")
// Lista jelen állapota: { "Capt. America", "Thor", "Hulk" };
// Indexek: 0 1 2
avengers.Insert(1,"Spiderman");
// Lista jelen állapota: { "Capt. America", "Spiderman", "Thor", "Hulk" };
// Indexek: 0 1 2 3
Az összes elem eltávolításához a Clear()
metódust kell használni, ami könnyen törli a lista teljes tartalmát.
myFloats.Clear();
Listák pár fontosabb metódusa
Contains()
: Megvizsgálja, hogy egy lista tartalmaz-e egy adott elemet.
Visszatérése egy logikai, azaz bool
típus érték (true
vagy false
).
List<string> colors = new (){"red", "green", "blue"};
bool hasGreen = colors.Contains("green"); // Visszatérési érték: true
IndexOf()
: Megkeresi egy listában egy adott elem indexét.
Visszatérési értéke az elem indexe, ha megtalálta, különben -1.
List<string> colors = new (){"red", "green", "blue"};
int index = colors.IndexOf("green"); // Visszatérési érték: 1
Reverse()
: A lista elemeinek megfordítása
List<int> numbers = new () {1, 2, 3, 4, 5};
numbers.Reverse(); // {5, 4, 3, 2, 1}
Sort()
: A lista elemeit rendezi.
List<int> numbers = new (){3, 7, 5, 1, 4};
numbers.Sort(); // {1, 3, 4, 5, 7}
Utóbbi két művelet (Reverse()
és Sort()
) csak olyan típusokon működik, amiken valami módon értelmezett a kisebb-nagyobb viszony. Pl.: számok, sztringek (ABC sorrend)
Később a sorba rendezésről bővebben: Sorozatok rendezése
A fenti metódusok elérhetők tömbökre is:
string[] array = { "Aa", "Bb", "Cc", "Dd", "Ee" };
int index = Array.IndexOf(array, "Bb"); // Megkeresi egy elem indexét (-1 ha nincs)
bool contains = Array.IndexOf(array, "Bb") != -1; // Tartalmazza-e a tömb az elemet?
Array.Reverse(array); // Megfordítja az array tömb elemeit
Array.Sort(words); // Sorba rendezi az array tömb elemeit
Egyéb fontos lista és tömb műveletek is léteznek. Érdemes idővel ezeknek utána olvasni.
Konvertálás tömb és lista közt
A tömbök és a listák nagyon hasonló adatszerkezetek, ezért könnyedén konvertálhatók át egymásba a következő módon:
int[] array = { 1, 3, 5, 7, 9 };
List<int> list = new (array); // Tömbből lista
List<int> list2 = new (){ 2, 4, 6, 8, 10 };
int[] array2 = list2.ToArray(); // Listából tömb
Sorozatok konvertálása string-gé
Ha egy listán vagy tömbön meghívjuk a ToString()
metódust, akkor az nem a sorozat tartalmát, csak a típusát fogja visszaadni string formában.
int[] array = { 1,2,3,4,5,6 };
List<string> list = new() { "Alma" , "Banán", "Citrom"};
string arraySt = array.ToString(); // "System.Int32[]"
string listSt = list.ToString(); // "System.Collections.Generic.List`1[System.Int32]"
A fenti lekérdezésnek így nem túl sok értelme van. Helyette a string.Join
metódust használjuk, amely a sorozat tartalmát írja ki. A függvénynek 2 paramétere van:
- Mi legyen két elem közti elválasztó karaktersor?
- Mi a sorozat, amin végig haladok
int[] array = { 1,2,3,4,5,6 };
List<string> list = new() { "Alma" , "Banán", "Citrom"};
string arraySt2 = string.Join(" - ", array); // "1 - 2 - 3 - 4 - 5 - 6"
string listSt2 = string.Join(", ", list); // "Alma, Banán, Citrom
A Foreach ciklus
A for
ciklussal könnyedén végigiterálhatunk, azaz végiglépegethetünk egy tömb vagy lista minden elemén.
string[] friends = { "Rachel", "Monica", "Phoebe", "Joey", "Chandler", "Ross" };
// Ez a ciklus kiírtja a tömb minden elemét
for (int i = 0; i < friends.Length; i++)
{
string friend = friends[i];
Console.WriteLine(friend);
}
Ugyanez egyszerűbben is megoldható egy foreach
ciklus segítségével:
foreach (string friend in friends )
{
Console.WriteLine(friend);
}
A foreach
ciklus indexelés nélkül nyújt módot a lista elemeinek végig iterálására. A foreach
ciklust általánosan a következőképp írunk le:
foreach (T item in collection)
{
// Ciklus törzse: Valamit kezdünk az adott elemmel
}
Ahol T
az iterálandó elemek típusa, item
pedig a ciklusmagban használható változó, ami az aktuális elemre hivatkozik, és collection
az iteráció alapjául szolgáló kollekció.
Fontos tudni, hogy a foreach
cikluson belül (a ciklus törzsében) csakis kiolvashatunk listákból, módosításokat nem lehet alkalmazni rajta. Például, a foreach
ciklusban nem lehet új elemet hozzáadni listához, vagy törölni belőle.
List<int> list = new List<int>() { 1, 2, 3 };
foreach (var e in list)
{
list[0] = 2; // 🚫 Futási idejű hiba! 🚫
list.Add(2); // 🚫 Futási idejű hiba! 🚫
list.RemoveAt(0); // 🚫 Futási idejű hiba! 🚫
list.Insert(0, 5); // 🚫 Futási idejű hiba! 🚫
}
// Lehet viszont tömb egy-egy elemét módosítani:
int[] array1 = { 1, 2, 3 };
foreach (var e in array1)
{
array1[0] = 2; // ✔️ Tökéletesen működik
}
Speciális eset: