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ı içindeki türlerin System.Collections.Generic yan etkisiz olduğu varsayılır. Bu nedenle, derleyici bu tür türlerin aracı değerler olarak kullanılabileceğini ancak aksi takdirde kullanıma sunulmadığı senaryoları iyileştirebilir.
  • Bir koleksiyondaki bazı geçerli .AddRange(x) üyeye yapılan çağrı, yineleme ve numaralandırılmış değerlerinin tümünü ile tek tek koleksiyonuna ekleme ile aynı son değerle x.Addsonuçlanıyor.

.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 uygulayarak System.Runtime.CompilerServices.CollectionBuilderAttribute 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ünde ReadOnlySpan<char>tek bir parametre 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.

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.