Aracılığıyla paylaş


Birleşim türleri (C# başvurusu)

Birleşim türü, birkaç büyük/küçük harf türünden biri olabilecek bir değeri temsil eder. Birleşimler her durum türünden örtük dönüştürmeler, kapsamlı desen eşleştirme ve gelişmiş null atanabilirlik izlemesi sağlar. Birleşim türünü bildirmek için anahtar sözcüğünü union kullanın:

public union Pet(Cat, Dog, Bird);

Bu bildirim, üç büyük/küçük harf türüyle bir Pet birleşim oluşturur: Cat, Dogve Bird. Herhangi bir büyük/küçük harf türü değerini bir Pet değişkene atayabilirsiniz. Derleyici, ifadelerin switch tüm büyük/küçük harf türlerini kapsamasını sağlar.

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.

Bir değerin tam olarak sabit bir tür kümesinden biri olması gerektiğinde ve derleyicinin her olasılığın işlendiğini zorlamasını istediğinizde birleşim bildirin. Yaygın senaryolar şunlardır:

  • Sonuç veya hata döndürür: Yöntem bir başarı değeri veya hata değeri döndürür ve çağıranın her ikisini de işlemesi gerekir. gibi union Result(Success, Error) bir birleşim, sonuç kümesini açık hale getirir.
  • İleti veya komut gönderme: Sistem kapalı ileti türleri kümesini işler. Birleşim, yeni ileti türlerinin henüz bunları işlemeyen her switch biri için derleme zamanı uyarıları üretmesini sağlar.
  • İşaretçi arabirimlerini veya soyut temel sınıfları değiştirme: Bir arabirim veya soyut sınıfı yalnızca desen eşleştirme için türleri gruplandırmak için kullanıyorsanız, birleşim devralma veya paylaşılan üyeler gerektirmeden kapsamlı denetim sağlar.

Birleşim, diğer tür bildirimlerinden önemli şekillerde farklıdır:

  • veya classstruct'nin aksine, birleşim yeni veri üyeleri tanımlamaz. Bunun yerine, mevcut türleri kapalı bir alternatif kümesine oluşturur.
  • bir birleşiminden interfacefarklı olarak, bildirimde servis talebi türlerinin tam listesini tanımlarsınız ve derleyici bu listeyi kapsamlı denetimler için kullanır.
  • bir birleşimden recordfarklı olarak eşitlik, kopyalama veya yapısızlaştırma davranışı eklemez. Birleşim, "hangi alanlara sahip?" yerine "hangi durumda?" konusuna odaklanır.

Önemli

.NET 11 Preview 2'de çalışma zamanı ve IUnion arabirimini UnionAttribute içermez. Birleşim türlerini kullanmak için bunları kendiniz bildirmeniz gerekir. Gerekli bildirimleri görmek için bkz. Birleşim uygulaması.

Birleşim bildirimleri

Birleşim bildirimi bir ad ve servis talebi türlerinin listesini belirtir:

public union Pet(Cat, Dog, Bird);

Büyük/küçük harf türleri sınıflar, yapılar, arabirimler object, tür parametreleri, null atanabilir türler ve diğer birleşimler de dahil olmak üzere öğesine dönüştüren herhangi bir tür olabilir. Aşağıdaki örneklerde farklı durum türü olasılıkları gösterilmektedir:

public record class Cat(string Name);
public record class Dog(string Name);
public record class Bird(string Name);
public record class None;
public record class Some<T>(T Value);
public union Option<T>(None, Some<T>);
public union IntOrString(int, string);

Bir servis talebi türü bir değer türü olduğunda (gibi int), birleşim Value özelliğinde depolandığında değer kutulanır. Birleşimler içeriklerini tek object? bir başvuru olarak depolar.

Birleşim bildirimi, bazı kısıtlamalara tabi bir yapı gibi ek üyeleri olan bir gövde içerebilir. Birleşim bildirimleri örnek alanlarını, otomatik özellikleri veya alan benzeri olayları içeremez. Derleyici bu oluşturucuları birleşim oluşturma üyeleri olarak oluşturduğundan, ortak oluşturucuları tek bir parametreyle de bildiremezsiniz:

public union OneOrMore<T>(T, IEnumerable<T>)
{
    public IEnumerable<T> AsEnumerable() => Value switch
    {
        T single => [single],
        IEnumerable<T> multiple => multiple,
        _ => []
    };
}

Birleşim dönüştürmeleri

Her büyük/küçük harf türünden birleşim türüne örtük bir birleşim dönüştürmesi vardır. Oluşturucuyu açıkça çağırmanız gerekmez:

static void BasicConversion()
{
    Pet pet = new Dog("Rex");
    Console.WriteLine(pet.Value); // output: Dog { Name = Rex }

    Pet pet2 = new Cat("Whiskers");
    Console.WriteLine(pet2.Value); // output: Cat { Name = Whiskers }
}

Birleşim dönüştürmeleri, karşılık gelen oluşturulan oluşturucuyu çağırarak çalışır. Aynı tür için kullanıcı tanımlı örtük dönüştürme işleci varsa, kullanıcı tanımlı işleç birleşim dönüştürmesine göre öncelik alır. Dönüştürme önceliği hakkında ayrıntılı bilgi için dil belirtimine bakın.

Birleşim türü olduğunda T null atanabilir birleşim yapısına (T?) birleşim dönüştürmesi de çalışır:

static void NullableUnionExample()
{
    Pet? maybePet = new Dog("Buddy");
    Pet? noPet = null;

    Console.WriteLine(Describe(maybePet)); // output: Dog: Buddy
    Console.WriteLine(Describe(noPet));    // output: no pet

    static string Describe(Pet? pet) => pet switch
    {
        Dog d => d.Name,
        Cat c => c.Name,
        Bird b => b.Name,
        null => "no pet",
    };
}

Birleşim eşleştirme

Birleşim türünde desen eşleşmesi yaptığınızda, desenler birleşim Value değerinin kendisine değil birleşim özelliğine uygulanır. Bu "sarmayı kaldırma" davranışı, birleşimin desen eşleştirmeye saydam olduğu anlamına gelir:

static void PatternMatching()
{
    Pet pet = new Dog("Rex");

    var name = pet switch
    {
        Dog d => d.Name,
        Cat c => c.Name,
        Bird b => b.Name,
    };
    Console.WriteLine(name); // output: Rex
}

İki desen bu kuralın özel durumlarıdır: var desen ve atma _ deseni özelliğine değil birleşim değerinin Value kendisine uygulanır. (Nullable<Pet> döndürdüğünde Pet?GetPet() birleşim değerini yakalamak için kullanınvar:

if (GetPet() is var pet) { /* pet is the Pet? value returned from GetPet */ }

Mantıksal desenlerde, her dal ayrı ayrı sarmalama kuralını izler. Aşağıdaki desen, null olmadığını ve null olmadığını test Pet? eder Value:

GetPet() switch
{
    var pet and not null => ..., // 'var pet' captures the Pet?; 'not null' checks Value
}

Uyarı

desenleri için Valuegeçerli olduğundan, gibi pet is Pet bir desen genellikle eşleşmez, çünkü Pet birleşimin kendisi değil birleşimin içeriğine göre test edilir.

Null eşleştirme

Yapı birleşimleri için desen null null olup olmadığını Value denetler:

static void NullHandling()
{
    Pet pet = default;
    Console.WriteLine(pet.Value is null); // output: True

    var description = pet switch
    {
        Dog d => d.Name,
        Cat c => c.Name,
        Bird b => b.Name,
        null => "no pet",
    };
    Console.WriteLine(description); // output: no pet
}

Sınıf tabanlı birleşimler için birleşim null başvurusunun kendisi null olduğunda veya Value özelliği null olduğunda başarılı olur:

Result<string>? result = null;
if (result is null) { /* true — the reference is null */ }

Result<string> empty = new Result<string>((string?)null);
if (empty is null) { /* true — Value is null */ }

Null atanabilir birleşim yapısı türleri ()Pet? için, null null atanabilir sarmalayıcının değeri olmadığında veya temel alınan birleşimin Value değeri null olduğunda başarılı olur.

Birleşim tükenmesi

bir switch birleşimin tüm büyük/küçük harf türlerini işlediğinde ifade kapsamlıdır. Derleyici yalnızca bir servis talebi türü işlenmediyse uyarır. Herhangi bir türle eşleşmesi için atma deseni (_) veya var deseni eklemeniz gerekmez:

static void PatternMatching()
{
    Pet pet = new Dog("Rex");

    var name = pet switch
    {
        Dog d => d.Name,
        Cat c => c.Name,
        Bird b => b.Name,
    };
    Console.WriteLine(name); // output: Rex
}

Union Value özelliğinin null durumu "belki null" ise, uyarıyı önlemek için de işlemeniz null gerekir:

static void NullHandling()
{
    Pet pet = default;
    Console.WriteLine(pet.Value is null); // output: True

    var description = pet switch
    {
        Dog d => d.Name,
        Cat c => c.Name,
        Bird b => b.Name,
        null => "no pet",
    };
    Console.WriteLine(description); // output: no pet
}

Null Olabilirlik

Derleyici, aşağıdaki kurallar aracılığıyla bir birleşimin Value özelliğinin null durumunu izler:

  • Bir servis talebi türünden birleşim değeri oluşturduğunuzda (oluşturucu veya birleşim dönüştürmesi aracılığıyla), Value gelen değerin null durumunu alır.
  • Kutulanmayan erişim deseninin HasValue veya TryGetValue(...) üyeleri birleşimin içeriğini sorguladığında, null durumu Value dalda true "null değil" olur.

Özel birleşim türleri

Derleyici bir bildirimi bir unionstruct bildirime dönüştürür. Yapısı özniteliğiyle [System.Runtime.CompilerServices.Union] işaretlenir, arabirimini IUnion uygular. Bir özelliğin yanı sıra her büyük/küçük harf türü için bir ortak oluşturucu ve örtük dönüştürme Value içerir. Oluşturulan formun görüşü vardır. Bu her zaman bir yapıdır, her zaman değer türündeki servis taleplerini kutular ve her zaman içeriği olarak object?depolar.

Sınıf tabanlı birleşim, özel depolama stratejisi, birlikte çalışma desteği gibi farklı davranışlara ihtiyacınız olduğunda veya var olan bir türü uyarlamak istiyorsanız, birleşim türünü el ile oluşturabilirsiniz.

Özniteliği olan herhangi bir [Union] sınıf veya yapı, temel birleşim desenini izlerse bir birleşim türüdür. Temel birleşim deseni şunları gerektirir:

  • [Union] Türündeki bir öznitelik.
  • Her biri tek bir değere veya parametreye sahip bir veya in daha fazla genel oluşturucu. Her oluşturucunun parametre türü bir servis talebi türü tanımlar.
  • Erişimci içeren (veya object) türünde object? bir get ortak Value özellik.

Tüm sendika üyeleri halka açık olmalıdır. Derleyici birleşim dönüştürmeleri, desen eşleştirme ve kapsamlı denetimler uygulamak için bu üyeleri kullanır. Ayrıca , kutulama olmayan erişim desenini uygulayabilir veya sınıf tabanlı bir birleşim türü oluşturabilirsiniz.

Derleyici, özel birleşim türlerinin şu davranış kurallarını karşıladığını varsayar:

  • Ses:Value Her zaman büyük/küçük harf türlerinden birinin değerini döndürür ve hiçbir zaman farklı türde bir değer vermeznull. Yapı birleşimleri default için bir Value üretir null.
  • Kararlılık: Bir servis talebi türünden birleşim değeri oluşturursanız, Value bu büyük/küçük harf türüyle eşleşir (veya null girişin ise ).null
  • Oluşturma eşdeğerliği: Bir değer örtük olarak iki farklı durum türüne dönüştürülebilirse, her iki oluşturma üyesi de aynı gözlemlenebilir davranışı üretir.
  • Erişim deseni tutarlılığı: HasValue varsa ve TryGetValue üyeleri, doğrudan denetlemeye Value eşdeğer şekilde davranır.

Aşağıdaki örnekte özel birleşim türü gösterilmektedir:

[System.Runtime.CompilerServices.Union]
public struct Shape : System.Runtime.CompilerServices.IUnion
{
    private readonly object? _value;

    public Shape(Circle value) { _value = value; }
    public Shape(Rectangle value) { _value = value; }

    public object? Value => _value;
}

public record class Circle(double Radius);
public record class Rectangle(double Width, double Height);
static void ManualUnionExample()
{
    Shape shape = new Shape(new Circle(5.0));

    var area = shape switch
    {
        Circle c => Math.PI * c.Radius * c.Radius,
        Rectangle r => r.Width * r.Height,
    };
    Console.WriteLine($"{area:F2}"); // output: 78.54
}

Kutulama dışı erişim deseni

Özel birleşim türü isteğe bağlı olarak, desen eşleştirme sırasında kutulama olmadan değer türü durumlarına kesin olarak yazılan erişim sağlamak için kutulama olmayan erişim desenini uygulayabilir. Bu düzen şunları gerektirir:

  • HasValue olmadığında döndüren trueValue türünde bool bir nullözellik.
  • Bir TryGetValue parametre aracılığıyla değeri döndüren bool ve teslim eden her durum türü için bir out yöntem.
[System.Runtime.CompilerServices.Union]
public struct IntOrBool : System.Runtime.CompilerServices.IUnion
{
    private readonly int _intValue;
    private readonly bool _boolValue;
    private readonly byte _tag; // 0 = none, 1 = int, 2 = bool

    public IntOrBool(int? value)
    {
        if (value.HasValue)
        {
            _intValue = value.Value;
            _tag = 1;
        }
    }

    public IntOrBool(bool? value)
    {
        if (value.HasValue)
        {
            _boolValue = value.Value;
            _tag = 2;
        }
    }

    public object? Value => _tag switch
    {
        1 => _intValue,
        2 => _boolValue,
        _ => null
    };

    public bool HasValue => _tag != 0;

    public bool TryGetValue(out int value)
    {
        value = _intValue;
        return _tag == 1;
    }

    public bool TryGetValue(out bool value)
    {
        value = _boolValue;
        return _tag == 2;
    }
}
static void NonBoxingExample()
{
    IntOrBool val = new IntOrBool((int?)42);

    var description = val switch
    {
        int i => $"int: {i}",
        bool b => $"bool: {b}",
    };
    Console.WriteLine(description); // output: int: 42
}

Derleyici TryGetValue , kutulama değer türlerinden kaçınan desen eşleştirmesi uygularken özelliği tercih Value eder.

Sınıf tabanlı birleşim türleri

Sınıf bir birleşim türü de olabilir. Bu birleşim türü, başvuru semantiğine veya devralma işlemine ihtiyacınız olduğunda kullanışlıdır:

[System.Runtime.CompilerServices.Union]
public class Result<T> : System.Runtime.CompilerServices.IUnion
{
    private readonly object? _value;

    public Result(T? value) { _value = value; }
    public Result(Exception? value) { _value = value; }

    public object? Value => _value;
}
static void ClassUnionExample()
{
    Result<string> ok = new Result<string>("success");
    Result<string> err = new Result<string>(new InvalidOperationException("failed"));

    Console.WriteLine(Describe(ok));  // output: OK: success
    Console.WriteLine(Describe(err)); // output: Error: failed

    static string Describe(Result<string> result) => result switch
    {
        string s => $"OK: {s}",
        Exception e => $"Error: {e.Message}",
        null => "null",
    };
}

Sınıf tabanlı birleşimler için desen hem null null başvuru hem de null Valueile eşleşir.

Birleşim uygulaması

Aşağıdaki öznitelik ve arabirim, derleme zamanında ve çalışma zamanında birleşim türlerini destekler:

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
    public sealed class UnionAttribute : Attribute;

    public interface IUnion
    {
        object? Value { get; }
    }
}

Derleyici tarafından oluşturulan birleşim bildirimleri uygular IUnion. kullanarak çalışma zamanında IUnionherhangi bir birleşim değerini de kontrol edebilirsiniz:

if (value is IUnion { Value: null }) { /* the union's value is null */ }

Bir union tür bildirdiğinizde, derleyici uygulayan IUnionbir yapı oluşturur. Örneğin, bildirim (public union Pet(Cat, Dog, Bird);) şunun Pet eşdeğeri olur:

[Union] public struct Pet : IUnion
{
    public Pet(Cat value) => Value = value;
    public Pet(Dog value) => Value = value;
    public Pet(Bird value) => Value = value;
    public object? Value { get; }
}

Önemli

.NET 11 Preview 2'de bu türler çalışma zamanına dahil değildir. Birleşim türlerini kullanmak için bunları projenizde bildirmeniz gerekir. Bunlar gelecekteki bir .NET önizlemesinde yer alacağız.

C# dil belirtimi

Daha fazla bilgi için bkz. Birleşimler özellik belirtimi.

Ayrıca bakınız