Aracılığıyla paylaş


Koleksiyon ifadeleri - C# dil başvurusu

Ortak koleksiyon değerleri oluşturmak için koleksiyon ifadesi kullanın. Koleksiyon ifadesi, birçok farklı koleksiyon türüne atayabileceğiniz bir ters söz dizimidir. Koleksiyon ifadesi ve [ köşeli ayraçlar arasında ] bir dizi öğe içerir.

C# dili başvuru belgesi, C# dilinin en son yayımlanan sürümünü gösterir. Ayrıca, yaklaşan dil sürümü için genel önizlemelerdeki özelliklere yönelik ilk belgeleri içerir.

Belgelerde ilk olarak dilin son üç sürümünde veya geçerli genel önizlemelerde sunulan tüm özellikler tanımlanır.

Tavsiye

Bir özelliğin C# dilinde ilk tanıtıldığı zamanları bulmak için C# dil sürümü geçmişi makalesine bakın.

Aşağıdaki örnek bir System.Span<T>string öğe bildirir ve bunları haftanın günlerine başlatır:

Span<string> weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
foreach (var day in weekDays)
{
    Console.WriteLine(day);
}

Bir koleksiyon ifadesini birçok farklı koleksiyon türüne dönüştürebilirsiniz. İlk örnekte, bir koleksiyon ifadesi kullanarak bir değişkenin nasıl başlatıldığı gösterilmiştir. Aşağıdaki kod, koleksiyon ifadesi kullanabileceğiniz diğer konumların çoğunu gösterir:

// Initialize private field:
private static readonly ImmutableArray<string> _months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

// property with expression body:
public IEnumerable<int> MaxDays =>
    [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

public int Sum(IEnumerable<int> values) =>
    values.Sum();

public void Example()
{
    // As a parameter:
    int sum = Sum([1, 2, 3, 4, 5]);
}

Bir derleme zamanı sabitinin beklendiği bir koleksiyon ifadesi kullanamazsınız; örneğin, bir sabit başlatılırken veya bir yöntem bağımsız değişkeni için varsayılan değer olarak.

Önceki örneklerin her ikisi de koleksiyon ifadesinin öğeleri olarak sabitleri kullanıyordu. Aşağıdaki örnekte gösterildiği gibi, öğeler için değişkenleri de kullanabilirsiniz:

string hydrogen = "H";
string helium = "He";
string lithium = "Li";
string beryllium = "Be";
string boron = "B";
string carbon = "C";
string nitrogen = "N";
string oxygen = "O";
string fluorine = "F";
string neon = "Ne";
string[] elements = [hydrogen, helium, lithium, beryllium, boron, carbon, nitrogen, oxygen, fluorine, neon];
foreach (var element in elements)
{
    Console.WriteLine(element);
}

Spread öğesi

Bir koleksiyon ifadesindeki satır içi koleksiyon değerlerini almak için bir spread öğesi.. kullanın. Aşağıdaki örnek, ünlülerin bir koleksiyonunu, ünsüzlerin koleksiyonunu ve "y" harfini birleştirerek tam alfabe için bir koleksiyon oluşturur. Bu koleksiyonlardan biri şunlardan biri olabilir:

string[] vowels = ["a", "e", "i", "o", "u"];
string[] consonants = ["b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
                       "n", "p", "q", "r", "s", "t", "v", "w", "x", "z"];
string[] alphabet = [.. vowels, .. consonants, "y"];

değerlendirildiğinde spread öğesi ..vowelsbeş öğe üretir: "a", "e", "i", "o"ve "u". Spread öğesi ..consonants dizideki consonants sayı olan 20 öğe üretir. Bir spread öğesindeki ifade, bir foreach deyimi kullanılarak numaralandırılabilir olmalıdır. Önceki örnekte gösterildiği gibi, yayma öğelerini bir koleksiyon ifadesindeki tek tek öğelerle birleştirebilirsiniz.

Dönüşümler

Bir koleksiyon ifadesini aşağıdakiler dahil olmak üzere farklı koleksiyon türlerine dönüştürebilirsiniz:

Uyarı

Satır içi dizileri başlatmak için koleksiyon ifadelerini kullanamazsınız. Satır içi diziler farklı başlatma söz dizimi gerektirir.

Önemli

Koleksiyon ifadesi, dönüştürmenin hedef türünden bağımsız olarak her zaman koleksiyon ifadesindeki tüm öğeleri içeren bir koleksiyon oluşturur. Örneğin, dönüştürmenin hedefi olduğunda System.Collections.Generic.IEnumerable<T>, oluşturulan kod koleksiyon ifadesini değerlendirir ve sonuçları bellek içi bir koleksiyonda depolar.

Bu davranış LINQ'tan farklıdır; burada sıra numaralandırılana kadar örneği oluşturulamayabilir. Numaralandırılamayacak sonsuz bir dizi oluşturmak için koleksiyon ifadelerini kullanamazsınız.

Derleyici, bir koleksiyon ifadesiyle bildirilen koleksiyonu oluşturmanın en yüksek performanslı yolunu belirlemek için statik çözümleme kullanır. Örneğin, boş koleksiyon ifadesi, []hedef başlatma işleminden sonra değiştirilmeyecekmiş gibi Array.Empty<T>() gerçekleştirilebilir. Hedef veya System.Span<T>System.ReadOnlySpan<T>olduğunda, depolama alanı yığın olarak ayrılmış olabilir. Koleksiyon ifadeleri özellik belirtimi, derleyicinin izlemesi gereken kuralları belirtir.

Birçok API, parametre olarak birden çok koleksiyon türüyle aşırı yüklenir. Bir koleksiyon ifadesi birçok farklı ifade türüne dönüştürülebildiğinden, bu API'ler doğru dönüştürmeyi belirtmek için koleksiyon ifadesinde atamalar gerektirebilir. Aşağıdaki dönüştürme kuralları bazı belirsizlikleri giderir:

  • Daha iyi bir koleksiyon türü dönüştürme yerine daha iyi bir öğe dönüştürme tercih edilir. Başka bir deyişle, koleksiyon ifadesindeki öğelerin türü koleksiyonun türünden daha önemlidir. Bu kurallar , koleksiyon ifadesinden daha iyi dönüştürme için özellik belirtiminde açıklanmıştır.
  • , Span<T>veya başka bir ReadOnlySpan<T> türe ref structdönüştürme, başvuru olmayan bir yapı türüne dönüştürmeden daha iyidir.
  • Bir arabirim türüne dönüştürme, arabirim türüne dönüştürmeden daha iyidir.

Bir koleksiyon ifadesini Span veya ReadOnlySpanöğesine dönüştürdüğünüzde, span nesnesinin güvenli bağlamı , yayılma alanına dahil edilen tüm öğelerin güvenli bağlamından gelir. Ayrıntılı kurallar için bkz . Koleksiyon ifadesi belirtimi.

Koleksiyon oluşturucusu

Koleksiyon ifadeleri iyi davranan herhangi bir koleksiyon türüyle çalışır. İyi davranmış bir koleksiyon aşağıdaki özelliklere sahiptir:

  • SayılabilirCountkoleksiyondaki veya Length değeri, numaralandırıldığında öğe sayısıyla aynı değeri üretir.
  • Ad alanı System.Collections.Generic içindeki türler yan etkisizdir. Derleyici, bu türlerin aracı değerler olarak kullanılabildiği senaryoları iyileştirebilir, ancak aksi takdirde bunları kullanıma sunmaz.
  • Bir koleksiyondaki geçerli .AddRange(x) üyeye yapılan çağrı, yineleme ve kullanarak .Addnumaralandırılmış değerlerinin tümünü tek tek koleksiyona ekleme ile aynı son değere x neden olur.

.NET çalışma zamanındaki tüm koleksiyon türleri düzgün şekilde davranır.

Uyarı

Özel bir koleksiyon türü düzgün davranmıyorsa, bu koleksiyon türünü koleksiyon ifadeleriyle kullandığınızda davranış tanımlanmamış olur.

Türleriniz, bir Create() yöntem yazarak ve oluşturucu yöntemini belirtmek için koleksiyon türüne System.Runtime.CompilerServices.CollectionBuilderAttribute özniteliğini uygulayarak koleksiyon ifadesi desteğini kabul eder. Örneğin, 80 karakterlik sabit uzunlukta arabellekler kullanan bir uygulama düşünün. Bu sınıf aşağıdaki koda benzer olabilir:

public class LineBuffer : IEnumerable<char>
{
    private readonly char[] _buffer;
    private readonly int _count;

    public LineBuffer(ReadOnlySpan<char> buffer)
    {
        _buffer = new char[buffer.Length];
        _count = buffer.Length;
        for (int i = 0; i < _count; i++)
        {
            _buffer[i] = buffer[i];
        }
    }

    public int Count => _count;
    
    public char this[int index]
    {
        get
        {
            if (index >= _count)
                throw new IndexOutOfRangeException();
            return _buffer[index];
        }
    }

    public IEnumerator<char> GetEnumerator()
    {
        for (int i = 0; i < _count; i++)
        {
            yield return _buffer[i];
        }
    }
    
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

    // etc
}

Aşağıdaki örnekte gösterildiği gibi koleksiyon ifadeleriyle kullanmak istiyorsunuz:

LineBuffer line = ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'];

türü LineBuffer uygular IEnumerable<char>, böylece derleyici bunu bir öğe koleksiyonu char olarak tanır. Uygulanan System.Collections.Generic.IEnumerable<T> arabirimin tür parametresi, öğe türünü gösterir. Bir nesneye koleksiyon ifadeleri LineBuffer atayabilmek için uygulamanıza iki ekleme yapmanız gerekir. İlk olarak, bir yöntem içeren bir Create sınıf oluşturmanız gerekir:

internal static class LineBufferBuilder
{
    internal static LineBuffer Create(ReadOnlySpan<char> values) => new LineBuffer(values);
}

Create yöntemi bir LineBuffer nesnesi döndürmelidir ve türünün ReadOnlySpan<char>son parametresini almalıdır. öğesinin ReadOnlySpan tür parametresi, koleksiyonun öğe türüyle eşleşmelidir. Genel bir koleksiyon döndüren oluşturucu yönteminin parametresi geneldir ReadOnlySpan<T> . yöntemine ve staticerişilebilir olması gerekir.

C# 15'den başlayarak yöntemin Create parametresinden ReadOnlySpan<T> önce ek parametreleri olabilir. Koleksiyon ifadesindeki bir with(...) öğeyi kullanarak değerleri bu parametrelere geçirebilirsiniz. Ayrıntılar için bkz. Koleksiyon oluşturucu bağımsız değişkenleri .

Son olarak, sınıf bildirimine CollectionBuilderAttribute öğesini LineBuffer eklemeniz gerekir:

[CollectionBuilder(typeof(LineBufferBuilder), "Create")]

İlk parametre Builder sınıfının adını sağlar. İkinci öznitelik, oluşturucu yönteminin adını sağlar.

Koleksiyon ifadesi bağımsız değişkenleri

C# 15'den başlayarak, bir öğeyi koleksiyon ifadesindeki ilk öğe olarak kullanarak with(...) temel koleksiyonun oluşturucusunun veya fabrika yönteminin bağımsız değişkenlerini geçirebilirsiniz. Bu özellik, kapasite, karşılaştırıcılar veya diğer oluşturucu parametrelerini doğrudan koleksiyon ifadesi söz diziminde belirtmenizi sağlar. Daha fazla bilgi için bkz. koleksiyon ifadesi bağımsız değişkenleri özellik belirtimi.

with(...) öğesi koleksiyon ifadesindeki ilk öğe olmalıdır. öğesinde with(...) bildirilen bağımsız değişkenler uygun oluşturucuya geçirilir veya hedef türüne göre oluşturma yöntemine geçirilir. öğesindeki with bağımsız değişkenler için herhangi bir geçerli ifade kullanabilirsiniz.

Oluşturucu bağımsız değişkenleri

Hedef türü uygulayan System.Collections.IEnumerablebir sınıf veya yapı olduğunda içindeki bağımsız değişkenler with(...) değerlendirilir ve sonuçlar oluşturucuya geçirilir. Derleyici, en iyi eşleşen oluşturucuyu seçmek için aşırı yükleme çözümlemesi kullanır:

public void CollectionArgumentsExamples()
{
    string[] values = ["one", "two", "three"];

    // Pass capacity argument to List<T> constructor
    List<string> names = [with(capacity: values.Length * 2), .. values];

    // Pass comparer argument to HashSet<T> constructor
    HashSet<string> set = [with(StringComparer.OrdinalIgnoreCase), "Hello", "HELLO", "hello"];
    // set contains only one element because all strings are equal with OrdinalIgnoreCase

    // Pass capacity to IList<T> (uses List<T> constructor)
    IList<int> numbers = [with(capacity: 100), 1, 2, 3];
}

Yukarıdaki örnekte:

Koleksiyon oluşturucu bağımsız değişkenleri

ile System.Runtime.CompilerServices.CollectionBuilderAttributetürler için öğesinde with(...) bildirilen bağımsız değişkenler değerlendirilir ve sonuçlar parametresinden önce create yöntemine ReadOnlySpan<T> geçirilir. Bu özellik, oluşturma yöntemlerinin yapılandırma parametrelerini kabul etmesine olanak tanır:

internal static class MySetBuilder
{
    internal static MySet<T> Create<T>(ReadOnlySpan<T> items) => new MySet<T>(items);
    internal static MySet<T> Create<T>(IEqualityComparer<T> comparer, ReadOnlySpan<T> items) => 
        new MySet<T>(items, comparer);
}

Ardından öğesini kullanarak with(...) karşılaştırıcıyı geçirebilirsiniz:

public void CollectionBuilderArgumentsExample()
{
    // Pass comparer to a type with CollectionBuilder attribute
    // The comparer argument is passed before the ReadOnlySpan<T> parameter
    MySet<string> mySet = [with(StringComparer.OrdinalIgnoreCase), "A", "a", "B"];
    // mySet contains only two elements: "A" and "B"
}

Create yöntemi, sağlanan bağımsız değişkenlere göre aşırı yükleme çözümlemesi kullanılarak seçilir. ReadOnlySpan<T> Koleksiyon öğelerini içeren her zaman son parametredir.

Arabirim hedef türleri

Çeşitli arabirim hedef türleri koleksiyon ifadesi bağımsız değişkenlerini destekler. Aşağıdaki tabloda desteklenen arabirimler ve bunların ilgili oluşturucu imzaları gösterilmektedir:

Arayüz Desteklenen with öğeler
IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T> () (yalnızca boş)
ICollection<T>, IList<T> (), (int capacity)

ve ICollection<T>içinIList<T>, derleyici belirtilen oluşturucu ile bir System.Collections.Generic.List<T> kullanır.

Restrictions

with(...) öğesi aşağıdaki kısıtlamalara sahiptir:

  • Koleksiyon ifadesindeki ilk öğe olmalıdır.
  • Bağımsız değişkenlerin türü olamaz dynamic .
  • Diziler veya span türleri (Span<T>, ReadOnlySpan<T>) için desteklenmez.