Koleksiyonlar (C#)

Birçok uygulama için, ilgili nesne gruplarını oluşturmak ve yönetmek istiyor. Nesneleri grup etmenin iki yolu vardır: nesne dizileri oluşturarak ve nesne koleksiyonları oluşturarak.

Diziler en çok sabit sayıda kesin türü türüne sahip nesne oluşturmak ve bu nesnelerle çalışmak için kullanışlıdır. Diziler hakkında bilgi için bkz. Diziler.

Koleksiyonlar, nesne gruplarıyla çalışmak için daha esnek bir yol sağlar. Dizilerden farklı olarak, uygulamanın ihtiyaçları değiştikçe, birlikte çalışmakta olan nesne grubu dinamik olarak büyüyebilir ve küçülebilir. Bazı koleksiyonlar için, anahtarı kullanarak nesneyi hızlı bir şekilde almak için koleksiyona koyarak herhangi bir nesneye anahtar atabilirsiniz.

Koleksiyon bir sınıftır, bu nedenle bu koleksiyona öğe ekleymeden önce sınıfın bir örneğini bildirin.

Koleksiyonunuz yalnızca bir veri türünde öğeler içeriyorsa, ad alanı sınıflarından birini System.Collections.Generic kullanabilirsiniz. Genel koleksiyon, tür güvenliğini zorunlu bulundurarak başka veri türü eklenmez. Bir öğeyi genel bir koleksiyondan almak için veri türünü belirlemeniz veya dönüştürmeye gerek yoktur.

Not

Bu konudaki örnekler için ve ad alanları için using System.Collections.Generic System.Linq yönergelerini içerir.

Bu konu başlığında

Basit Koleksiyon Kullanma

Bu bölümdeki örneklerde, kesin olarak türü kesin olarak belirtilen nesneler List<T> listesiyle çalışmana olanak sağlayan genel sınıfı kullanılır.

Aşağıdaki örnek bir dize listesi oluşturur ve ardından foreach deyimini kullanarak dizeler arasında yineler.

// Create a list of strings.
var salmons = new List<string>();
salmons.Add("chinook");
salmons.Add("coho");
salmons.Add("pink");
salmons.Add("sockeye");

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

Bir koleksiyonun içeriği önceden biliniyorsa, koleksiyonu başlatmak için bir koleksiyon başlatıcısı kullanabilirsiniz. Daha fazla bilgi için bkz. Nesne ve Koleksiyon Başlatıcıları.

Aşağıdaki örnek, koleksiyona öğe eklemek için bir koleksiyon başlatıcısı kullanılma dışında önceki örnekle aynıdır.

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

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

Bir koleksiyonda devam etmek için deyimi foreach yerine for deyimi kullanabilirsiniz. Bunu, koleksiyon öğelerine dizin konumundan erişerek gerçekleştirin. Öğelerin dizini 0'dan başlar ve öğe sayısı eksi 1'de biter.

Aşağıdaki örnek, yerine kullanarak bir koleksiyonun öğeleriyle aynı for şekilde devam foreach eder.

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

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

Aşağıdaki örnek, kaldırılama nesnesini belirterek bir öğeyi koleksiyondan kaldırır.

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

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

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

Aşağıdaki örnek, öğeleri genel bir listeden kaldırır. Deyimi yerine foreach azalan for düzende devam eden bir deyim kullanılır. Bunun nedeni, RemoveAt yönteminin kaldırılan bir öğeden sonra öğelerin daha düşük bir dizin değerine sahip olacak şekilde neden olduğudur.

var numbers = new List<int> { 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çinde öğelerin türü için List<T> kendi sınıfınızı da tanımlayabilirsiniz. Aşağıdaki örnekte tarafından Galaxy kullanılan sınıfı List<T> kodda tanımlanmıştır.

private static void IterateThroughList()
{
    var theGalaxies = new List<Galaxy>
        {
            new Galaxy() { Name="Tadpole", MegaLightYears=400},
            new Galaxy() { Name="Pinwheel", MegaLightYears=25},
            new Galaxy() { Name="Milky Way", MegaLightYears=0},
            new Galaxy() { 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; }
}

Koleksiyon Türleri

Birçok yaygın koleksiyon .NET tarafından sağlanır. Her koleksiyon türü belirli bir amaç için tasarlanmıştır.

Yaygın koleksiyon sınıflarının bazıları bu bölümde açıklanmıştır:

System.Collections.Generic Sınıfları

Ad alanı sınıflarından birini kullanarak genel bir koleksiyon System.Collections.Generic oluşturabilirsiniz. Genel koleksiyon, koleksiyonda her öğe aynı veri türüne sahip olduğunda yararlıdır. Genel bir koleksiyon, yalnızca istenen veri türünün eklenmeye izin vererek güçlü yazma zorlar.

Aşağıdaki tabloda ad alanının sık kullanılan sınıflarının bazıları System.Collections.Generic listelemektedir:

Sınıf Açıklama
Dictionary<TKey,TValue> Anahtara göre düzenlenmiş bir anahtar/değer çifti koleksiyonunu temsil eder.
List<T> Dizin tarafından erişilebilen nesnelerin listesini temsil eder. Listeleri aramak, sıralamak ve değiştirmek için yöntemler sağlar.
Queue<T> Nesnelerden ilk in, ilk çıkar (FIFO) koleksiyonunu temsil eder.
SortedList<TKey,TValue> İlişkili uygulamaya göre anahtara göre sıralanmış bir anahtar/değer çifti koleksiyonunu temsil IComparer<T> eder.
Stack<T> Nesnelerden son gelen, ilk çıkar (BAKİP) koleksiyonunu temsil eder.

Daha fazla bilgi için bkz. Yaygın Olarak Kullanılan Koleksiyon Türleri, Koleksiyon Sınıfı Seçmeve System.Collections.Generic .

System.Collections.Concurrent Sınıfları

4 .NET Framework sonraki sürümlerde, ad alanı koleksiyonları birden çok iş parçacığından koleksiyon öğelerine erişmek için verimli iş System.Collections.Concurrent parçacığı güvenli işlemler sağlar.

Birden çok iş parçacığı koleksiyona eşzamanlı olarak erişirken ve ad alanlarında karşılık gelen türler yerine ad System.Collections.Concurrent System.Collections.Generic alanı sınıfları System.Collections kullanılmalıdır. Daha fazla bilgi için bkz. Thread-Kasa Koleksiyonları ve System.Collections.Concurrent .

Ad alanına dahil edilen System.Collections.Concurrent bazı sınıflar , , ve BlockingCollection<T> ConcurrentDictionary<TKey,TValue> ConcurrentQueue<T> ConcurrentStack<T> sınıflarıdır.

System.Collections Sınıfları

Ad alanı System.Collections sınıfları, öğeleri özel olarak türüne sahip nesneler olarak değil türünde nesneler olarak Object depolamaz.

Mümkün olduğunda, ad alanı eski türleri yerine ad alanı veya System.Collections.Generic System.Collections.Concurrent ad alanı genel koleksiyonları System.Collections kullanılmalıdır.

Aşağıdaki tabloda ad alanı içinde sık kullanılan sınıflardan bazıları System.Collections listelemektedir:

Sınıf Açıklama
ArrayList Boyutu gerektiğinde dinamik olarak artırılmış bir nesne dizisini temsil eder.
Hashtable Anahtarın karma koduna göre düzenlenmiş bir anahtar/değer çifti koleksiyonunu temsil eder.
Queue Nesnelerden ilk in, ilk çıkar (FIFO) koleksiyonunu temsil eder.
Stack Nesnelerden son gelen, ilk çıkar (BAKİP) koleksiyonunu temsil eder.

Ad alanı, yalnızca dize koleksiyonları, bağlantılı liste ve karma sözlükler gibi özel ve kesin System.Collections.Specialized türe sahip koleksiyon sınıfları sağlar.

Anahtar/Değer Çiftleri Koleksiyonu Uygulama

Genel Dictionary<TKey,TValue> koleksiyon, her öğenin anahtarını kullanarak bir koleksiyonda öğelere erişmeye olanak sağlar. Sözlüğüne yapılan her ekleme bir değerden ve ilişkili anahtarın değerinden oluşur. Sınıf karma tablo olarak uygulana olduğundan, anahtarını Dictionary kullanarak bir değeri almak hızlıdır.

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

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);
    }
}

private static Dictionary<string, Element> BuildDictionary()
{
    var elements = new Dictionary<string, Element>();

    AddToDictionary(elements, "K", "Potassium", 19);
    AddToDictionary(elements, "Ca", "Calcium", 20);
    AddToDictionary(elements, "Sc", "Scandium", 21);
    AddToDictionary(elements, "Ti", "Titanium", 22);

    return elements;
}

private static void AddToDictionary(Dictionary<string, Element> elements,
    string symbol, string name, int atomicNumber)
{
    Element theElement = new Element();

    theElement.Symbol = symbol;
    theElement.Name = name;
    theElement.AtomicNumber = atomicNumber;

    elements.Add(key: theElement.Symbol, value: theElement);
}

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

Bunun yerine koleksiyonu derlemek için bir koleksiyon Dictionary başlatıcısı kullanmak için, BuildDictionary ve yöntemlerini aşağıdaki yöntemle AddToDictionary değiştirebilirsiniz.

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

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

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

    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 yöntemini TryGetValue kullanarak bir öğeyi anahtara göre hızla bulur.

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

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

Koleksiyona Erişmek için LINQ Kullanma

LinQ (Language-Integrated Query) koleksiyonlara erişmek için kullanılabilir. LINQ sorguları filtreleme, sıralama ve gruplama özellikleri sağlar. Daha fazla bilgi için bkz. C# Başlarken LINQ ile birlikte.

Aşağıdaki örnek genel bir linq sorgusu List çalıştırı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()
{
    return new List<Element>
    {
        { new Element() { Symbol="K", Name="Potassium", AtomicNumber=19}},
        { new Element() { Symbol="Ca", Name="Calcium", AtomicNumber=20}},
        { new Element() { Symbol="Sc", Name="Scandium", AtomicNumber=21}},
        { new Element() { Symbol="Ti", Name="Titanium", AtomicNumber=22}}
    };
}

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

Koleksiyonu Sıralama

Aşağıdaki örnek, bir koleksiyonu sıralama yordamını göstermektedir. Örnek, içinde depolanan Car sınıfının örneklerini List<T> sıralar. Carsınıfı, IComparable<T> yönteminin uygulanmasını gerektiren CompareTo arabirimini kullanır.

yöntemine yapılan CompareTo her çağrı, sıralama için kullanılan tek bir karşılaştırma yapar. yönteminde kullanıcı tarafından yazılan CompareTo kod, geçerli nesnenin başka bir nesneyle her karşılaştırması için bir değer döndürür. Geçerli nesne diğer nesneden küçükse döndürülen değer sıfırdan küçük, geçerli nesne diğer nesneden büyükse sıfırdan, eşitse sıfırdan büyüktür. Bu, kodda büyüktür, küçük ve eşittir ölçütlerini tanımlamaya olanak sağlar.

yönteminde ListCars deyimi cars.Sort() listeyi sıralar. yöntemine yapılan Sort bu List<T> çağrı, yönteminin CompareTo içinde nesneler için otomatik olarak Car çağrılma neden List olur.

private static void ListCars()
{
    var cars = new List<Car>
    {
        { new Car() { Name = "car1", Color = "blue", Speed = 20}},
        { new Car() { Name = "car2", Color = "red", Speed = 50}},
        { new Car() { Name = "car3", Color = "green", Speed = 10}},
        { new Car() { Name = "car4", Color = "blue", Speed = 50}},
        { new Car() { Name = "car5", Color = "blue", Speed = 30}},
        { new Car() { Name = "car6", Color = "red", Speed = 60}},
        { new Car() { Name = "car7", Color = "green", Speed = 50}}
    };

    // Sort the cars by color alphabetically, and then by speed
    // in descending order.
    cars.Sort();

    // View all of the cars.
    foreach (Car thisCar in cars)
    {
        Console.Write(thisCar.Color.PadRight(5) + " ");
        Console.Write(thisCar.Speed.ToString() + " ");
        Console.Write(thisCar.Name);
        Console.WriteLine();
    }

    // Output:
    //  blue  50 car4
    //  blue  30 car5
    //  blue  20 car1
    //  green 50 car7
    //  green 10 car3
    //  red   60 car6
    //  red   50 car2
}

public class Car : IComparable<Car>
{
    public string Name { get; set; }
    public int Speed { get; set; }
    public string Color { get; set; }

    public int CompareTo(Car other)
    {
        // A call to this method makes a single comparison that is
        // used for sorting.

        // Determine the relative order of the objects being compared.
        // Sort by color alphabetically, and then by speed in
        // descending order.

        // Compare the colors.
        int compare;
        compare = String.Compare(this.Color, other.Color, true);

        // If the colors are the same, compare the speeds.
        if (compare == 0)
        {
            compare = this.Speed.CompareTo(other.Speed);

            // Use descending order for speed.
            compare = -compare;
        }

        return compare;
    }
}

Özel Koleksiyon Tanımlama

veya arabirimini kullanarak bir koleksiyon IEnumerable<T> IEnumerable tanımlayabilirsiniz.

Özel bir koleksiyon tanımlayabilirsiniz ancak bunun yerine bu makalenin başlarındaki Koleksiyon Türleri makalesinde açıklanan .NET'e dahil edilen koleksiyonları kullanmak genellikle daha iyidir.

Aşağıdaki örnek adlı özel bir koleksiyon sınıfı AllColors tanımlar. Bu sınıf, IEnumerable yönteminin uygulanmasını gerektiren GetEnumerator arabirimini kullanır.

yöntemi GetEnumerator sınıfının bir örneğini ColorEnumerator döndürür. ColorEnumerator , IEnumerator özelliğin, yöntemin ve yöntemin uygulanmasını Current MoveNext gerektiren Reset arabirimini kullanır.

private static void ListColors()
{
    var colors = new AllColors();

    foreach (Color theColor in colors)
    {
        Console.Write(theColor.Name + " ");
    }
    Console.WriteLine();
    // Output: red blue green
}

// Collection class.
public class AllColors : System.Collections.IEnumerable
{
    Color[] _colors =
    {
        new Color() { Name = "red" },
        new Color() { Name = "blue" },
        new Color() { Name = "green" }
    };

    public System.Collections.IEnumerator GetEnumerator()
    {
        return new ColorEnumerator(_colors);

        // Instead of creating a custom enumerator, you could
        // use the GetEnumerator of the array.
        //return _colors.GetEnumerator();
    }

    // Custom enumerator.
    private class ColorEnumerator : System.Collections.IEnumerator
    {
        private Color[] _colors;
        private int _position = -1;

        public ColorEnumerator(Color[] colors)
        {
            _colors = colors;
        }

        object System.Collections.IEnumerator.Current
        {
            get
            {
                return _colors[_position];
            }
        }

        bool System.Collections.IEnumerator.MoveNext()
        {
            _position++;
            return (_position < _colors.Length);
        }

        void System.Collections.IEnumerator.Reset()
        {
            _position = -1;
        }
    }
}

// Element class.
public class Color
{
    public string Name { get; set; }
}

Yineleyiciler

Bir koleksiyon üzerinde özel yineleme gerçekleştirmek için bir tekrarlayıcı kullanılır. Bir tekrarlayıcı yöntem veya erişimci get olabilir. Bir tekrarlayıcı, koleksiyonun yield return bir kez geri dönmek için bir yield return deyimi kullanır.

Bir foreach deyimi kullanarak bir iterator'ı çağırma. Döngülerin her foreach yinelemesi, tekrarlayıcıyı çağrılır. Bir yield return deyimine tekrarlayıcıda ulaşıldıklarında bir ifade döndürülür ve kodda geçerli konum korunur. Yürütme, bir sonraki kez tekrar çağrıldıktan sonra bu konumdan yeniden başlatılır.

Daha fazla bilgi için bkz. Tekrarlayıcılar (C#).

Aşağıdaki örnekte bir bir iterator yöntemi 2. Tekrarlayıcı yöntemi, bir yield return döngü içinde olan bir for deyimine sahip. yönteminde, deyim gövdesinin her yinelemesi, bir sonraki deyime devam edecek yineleme ListEvenNumbers foreach yöntemine bir çağrı yield return 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;
        }
    }
}

Ayrıca bkz.