Koleksiyonlar

.NET çalışma zamanı, ilgili nesne gruplarını depolayan ve yöneten birçok koleksiyon türü sağlar. , System.Span<T>ve System.Memory<T> gibi System.Arraybazı koleksiyon türleri C# dilinde tanınır. Buna ek olarak, gibi System.Collections.Generic.IEnumerable<T> arabirimler bir koleksiyonun öğelerini numaralandırmak için dilde tanınır.

Koleksiyonlar, nesne gruplarıyla çalışmak için esnek bir yol sağlar. Farklı koleksiyonları şu özelliklere göre sınıflandırabilirsiniz:

  • Öğe erişimi: Her koleksiyon, her öğeye sırayla erişmek için numaralandırılabilir. Bazı koleksiyonlar, öğenin sıralı koleksiyondaki konumu olan dizine göre öğelere erişiyor. En yaygın örnek: System.Collections.Generic.List<T>. Diğer koleksiyonlar, bir değerin tek bir anahtarla ilişkilendirildiği anahtara göre öğelere erişilir. En yaygın örnek: System.Collections.Generic.Dictionary<TKey,TValue>. Uygulamanızın öğelere nasıl eriştiğine bağlı olarak bu koleksiyon türleri arasında seçim yapabilirsiniz.
  • Performans profili: Her koleksiyonun öğe ekleme, öğe bulma veya öğe kaldırma gibi eylemler için farklı performans profilleri vardır. Uygulamanızda en çok kullanılan işlemlere göre bir koleksiyon türü seçebilirsiniz.
  • Dinamik olarak büyütme ve küçültme: Koleksiyonların çoğu öğeleri dinamik olarak eklemeyi veya kaldırmayı destekler. Özellikle, Array, System.Span<T>ve System.Memory<T> yapma.

Çalışma zamanı, bu özelliklere ek olarak, öğelerin eklenmesini veya kaldırılmasını ya da koleksiyonun öğelerinin değiştirilmesini engelleyen özel koleksiyonlar sağlar. Diğer özel koleksiyonlar, çok iş parçacıklı uygulamalarda eşzamanlı erişim için güvenlik sağlar.

Tüm koleksiyon türlerini .NET API başvurusunda bulabilirsiniz. Daha fazla bilgi için bkz . Yaygın Kullanılan Koleksiyon Türleri ve Koleksiyon Sınıfı Seçme.

Not

Bu makaledeki örnekler için ve System.Linq ad alanları için System.Collections.Generic using yönergeleri eklemeniz gerekebilir.

Diziler ile System.Array temsil edilir ve C# dilinde söz dizimi desteğine sahiptir. Bu söz dizimi, dizi değişkenleri için daha kısa bildirimler sağlar.

System.Span<T>ref struct, bu öğeleri kopyalamadan bir dizi öğe üzerinde anlık görüntü sağlayan bir türdür. Derleyici, başvurduktan sonra artık kapsam içinde olmadığından emin olmak Span için güvenlik kurallarını zorunlu kılar. Performansı geliştirmek için birçok .NET API'sinde kullanılır. Memory<T> türü kullanamıyorsanız benzer davranışlar ref struct sağlar.

C# 12 ile başlayarak, koleksiyon türlerinin tümü bir Koleksiyon ifadesi kullanılarak başlatılabilir.

Dizinlenebilir koleksiyonlar

Dizinlenebilir koleksiyon , her öğeye kendi dizinini kullanarak erişebileceğiniz koleksiyondur. Dizini, dizide ondan önceki öğelerin sayısıdır. Bu nedenle, dizine 0 göre öğe başvurusu ilk öğedir, dizin 1 ikinci öğedir, vb. Bu örneklerde List<T> sınıfı kullanılır. En yaygın dizinlenebilir koleksiyon.

Aşağıdaki örnek bir dize listesi oluşturup başlatır, bir öğeyi kaldırır ve listenin sonuna bir öğe ekler. Her değişiklikten sonra, bir foreach deyimi veya for bir döngü kullanarak dizeleri yineler:

// Create a list of strings by using a
// collection initializer.
List<string> salmons = ["chinook", "coho", "pink", "sockeye"];

// Iterate through the list.
foreach (var salmon in salmons)
{
    Console.Write(salmon + " ");
}
// Output: chinook coho pink sockeye

// Remove an element from the list by specifying
// the object.
salmons.Remove("coho");


// Iterate using the index:
for (var index = 0; index < salmons.Count; index++)
{
    Console.Write(salmons[index] + " ");
}
// Output: chinook pink sockeye

// Add the removed element
salmons.Add("coho");
// Iterate through the list.
foreach (var salmon in salmons)
{
    Console.Write(salmon + " ");
}
// Output: chinook pink sockeye coho

Aşağıdaki örnek, dizine göre bir listeden öğeleri kaldırır. Deyimi foreach yerine azalan sırada yineleyen bir for deyim kullanır. yöntemi, RemoveAt kaldırılan bir öğeden sonraki öğelerin daha düşük bir dizin değerine sahip olmasına neden olur.

List<int> numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

// Remove odd numbers.
for (var index = numbers.Count - 1; index >= 0; index--)
{
    if (numbers[index] % 2 == 1)
    {
        // Remove the element by specifying
        // the zero-based index in the list.
        numbers.RemoveAt(index);
    }
}

// Iterate through the list.
// A lambda expression is placed in the ForEach method
// of the List(T) object.
numbers.ForEach(
    number => Console.Write(number + " "));
// Output: 0 2 4 6 8

içindeki List<T>öğelerin türü için kendi sınıfınızı da tanımlayabilirsiniz. Aşağıdaki örnekte, Galaxy tarafından List<T> kullanılan sınıfı kodda tanımlanır.

private static void IterateThroughList()
{
    var theGalaxies = new List<Galaxy>
    {
        new (){ Name="Tadpole", MegaLightYears=400},
        new (){ Name="Pinwheel", MegaLightYears=25},
        new (){ Name="Milky Way", MegaLightYears=0},
        new (){ Name="Andromeda", MegaLightYears=3}
    };

    foreach (Galaxy theGalaxy in theGalaxies)
    {
        Console.WriteLine(theGalaxy.Name + "  " + theGalaxy.MegaLightYears);
    }

    // Output:
    //  Tadpole  400
    //  Pinwheel  25
    //  Milky Way  0
    //  Andromeda  3
}

public class Galaxy
{
    public string Name { get; set; }
    public int MegaLightYears { get; set; }
}

Anahtar/değer çifti koleksiyonları

Bu örneklerde Dictionary<TKey,TValue> sınıfı kullanılır. En yaygın sözlük koleksiyonu. Sözlük koleksiyonu, her öğenin anahtarını kullanarak koleksiyondaki öğelere erişmenizi sağlar. Sözlüğe yapılan her ekleme bir değerden ve ilişkili anahtarından oluşur.

Aşağıdaki örnek bir Dictionary koleksiyon oluşturur ve deyimini kullanarak foreach sözlükte yinelenir.

private static void IterateThruDictionary()
{
    Dictionary<string, Element> elements = BuildDictionary();

    foreach (KeyValuePair<string, Element> kvp in elements)
    {
        Element theElement = kvp.Value;

        Console.WriteLine("key: " + kvp.Key);
        Console.WriteLine("values: " + theElement.Symbol + " " +
            theElement.Name + " " + theElement.AtomicNumber);
    }
}

public class Element
{
    public required string Symbol { get; init; }
    public required string Name { get; init; }
    public required int AtomicNumber { get; init; }
}

private static Dictionary<string, Element> BuildDictionary() =>
    new ()
    {
        {"K",
            new (){ Symbol="K", Name="Potassium", AtomicNumber=19}},
        {"Ca",
            new (){ Symbol="Ca", Name="Calcium", AtomicNumber=20}},
        {"Sc",
            new (){ Symbol="Sc", Name="Scandium", AtomicNumber=21}},
        {"Ti",
            new (){ Symbol="Ti", Name="Titanium", AtomicNumber=22}}
    };

Aşağıdaki örnek, bir öğeyi anahtara ContainsKey göre hızlı bir şekilde bulmak için yöntemini ve Item[] özelliğini Dictionary kullanır. özelliği, Item C# dilinde kullanarak koleksiyondaki elements bir öğeye elements[symbol] erişmenizi sağlar.

if (elements.ContainsKey(symbol) == false)
{
    Console.WriteLine(symbol + " not found");
}
else
{
    Element theElement = elements[symbol];
    Console.WriteLine("found: " + theElement.Name);
}

Aşağıdaki örnek bunun yerine bir öğeyi TryGetValue anahtara göre hızlı bir şekilde bulmak için yöntemini kullanır.

if (elements.TryGetValue(symbol, out Element? theElement) == false)
    Console.WriteLine(symbol + " not found");
else
    Console.WriteLine("found: " + theElement.Name);

Yineleyiciler

Yineleyici, bir koleksiyon üzerinde özel yineleme gerçekleştirmek için kullanılır. Yineleyici bir yöntem veya get erişimci olabilir. Yineleyici, koleksiyonun her öğesini birer birer döndürmek için bir yield return deyimi kullanır.

Bir foreach deyimi kullanarak yineleyici çağırırsınız. Döngünün foreach her yinelemesi yineleyiciyi çağırır. Yineleyicide bir yield return deyime ulaşıldığında, bir ifade döndürülür ve koddaki geçerli konum korunur. Yineleyici bir sonraki çağrılışında yürütme bu konumdan yeniden başlatılır.

Daha fazla bilgi için bkz . Yineleyiciler (C#).

Aşağıdaki örnekte yineleyici yöntemi kullanılır. Yineleyici yöntemi bir yield return döngü içinde for bir deyimine sahiptir. yönteminde ListEvenNumbers , deyim gövdesinin foreach her yinelemesi bir sonraki yield return deyime devam eden yineleyici yöntemine bir çağrı oluşturur.

private static void ListEvenNumbers()
{
    foreach (int number in EvenSequence(5, 18))
    {
        Console.Write(number.ToString() + " ");
    }
    Console.WriteLine();
    // Output: 6 8 10 12 14 16 18
}

private static IEnumerable<int> EvenSequence(
    int firstNumber, int lastNumber)
{
    // Yield even numbers in the range.
    for (var number = firstNumber; number <= lastNumber; number++)
    {
        if (number % 2 == 0)
        {
            yield return number;
        }
    }
}

LINQ ve koleksiyonlar

Koleksiyonlara erişmek için dille tümleşik sorgu (LINQ) kullanılabilir. LINQ sorguları filtreleme, sıralama ve gruplandırma özellikleri sağlar. Daha fazla bilgi için bkz . C# dilinde LINQ kullanmaya başlama.

Aşağıdaki örnekte genel Listbir üzerinde LINQ sorgusu çalıştırılır. LINQ sorgusu sonuçları içeren farklı bir koleksiyon döndürür.

private static void ShowLINQ()
{
    List<Element> elements = BuildList();

    // LINQ Query.
    var subset = from theElement in elements
                 where theElement.AtomicNumber < 22
                 orderby theElement.Name
                 select theElement;

    foreach (Element theElement in subset)
    {
        Console.WriteLine(theElement.Name + " " + theElement.AtomicNumber);
    }

    // Output:
    //  Calcium 20
    //  Potassium 19
    //  Scandium 21
}

private static List<Element> BuildList() => new()
    {
        { new(){ Symbol="K", Name="Potassium", AtomicNumber=19}},
        { new(){ Symbol="Ca", Name="Calcium", AtomicNumber=20}},
        { new(){ Symbol="Sc", Name="Scandium", AtomicNumber=21}},
        { new(){ Symbol="Ti", Name="Titanium", AtomicNumber=22}}
    };