Yapı türleri (C# başvurusu)
Yapı türü (veya yapı türü), verileri ve ilgili işlevleri kapsülleyebilirsiniz. Yapı türü tanımlamak struct için anahtar sözcüğünü kullanırsiniz:
public struct Coords
{
public Coords(double x, double y)
{
X = x;
Y = y;
}
public double X { get; }
public double Y { get; }
public override string ToString() => $"({X}, {Y})";
}
Yapı türlerinin değer semantiği vardır. Başka bir ifadeyle, yapı türünde bir değişken, türünün bir örneğini içerir. Varsayılan olarak, değişken değerleri atamaya kopyalanır, bir yönteme bağımsız değişken iletir ve yöntem sonucu döndürer. Yapı türü değişkende, türün bir örneği kopyalanır. Daha fazla bilgi için bkz. Değer türleri.
Genellikle, çok az davranış sağlayan veya hiç davranış olmayan küçük veri merkezli türler tasarlamak için yapı türlerini kullanırsiniz. Örneğin, .NET bir s numarayı (hem tamsayı hem de gerçek), Booledeğerini , Unicodekarakterini , bir zaman örneğini temsil etmek için yapı türlerini kullanır. Bir türün davranışına odaklandıysanız sınıf tanımlamayı göz önünde bulundurabilirsiniz. Sınıf türlerinin başvuru semantiği vardır. Başka bir ifadeyle, sınıf türünde bir değişken, örneğin kendisine değil, türün bir örneğine başvuru içerir.
Yapı türleri değer semantiğine sahip olduğundan, sabit yapı türleri tanımlamanız önerilir.
readonly Yapı
C# 7.2'den itibaren, bir yapı türünün sabit olduğunu bildiren readonly değiştiricisini kullanırsiniz. Bir yapının tüm readonly veri üyeleri aşağıdaki gibi salt okunur olmalıdır:
- Herhangi bir alan bildiriminin
readonlydeğiştiricisi olmalıdır - Otomatik uygulananlar da dahil olmak üzere herhangi bir özelliğin salt okunur olması gerekir. C# 9.0 ve üzerinde bir özelliğin
initerişimcisi olabilir.
Bu, bir yapının hiçbir readonly üyesinin yapının durumunu değiştiren olmadığını garantiler. C# 8.0 ve üzerinde bu, oluşturucular dışındaki diğer örnek üyelerinin örtülü olduğu anlamına readonly gelir.
Not
readonlyYapıda, table başvuru türünün veri üyesi yine de kendi durumunun mutadi olabilir. Örneğin, bir örneği List<T> değiştiresiniz, ancak buna yeni öğeler eklersiniz.
Aşağıdaki kod, C# 9.0 ve üzerinde kullanılabilir olan yalnızca readonly init-property setter'ları ile bir yapı tanımlar:
public readonly struct Coords
{
public Coords(double x, double y)
{
X = x;
Y = y;
}
public double X { get; init; }
public double Y { get; init; }
public override string ToString() => $"({X}, {Y})";
}
readonly örnek üyeleri
C# 8.0'dan itibaren, bir örnek üyesinin yapının durumunu değiştirme olmadığını bildirerek readonly değiştiricisini de kullanabilirsiniz. Yapı türünün tamamını olarak bildire değil, yapının durumunu değiştirmeyen örnek üyelerini işaretlemek readonly readonly için değiştiricisini kullanın.
Bir readonly örnek üyesi içinde yapının örnek alanlarına atayabilirsiniz. Ancak, readonly bir üye olmayan bir üyeyi readonly çağır olabilir. Bu durumda derleyici yapı örneğinin bir kopyasını oluşturur ve bu kopyada üye readonly olmayanı arar. Sonuç olarak, özgün yapı örneği değiştirilmez.
Genellikle, readonly değiştiriciyi aşağıdaki örnek üyelerine uygulayabilirsiniz:
Yöntemler:
public readonly double Sum() { return X + Y; }Değiştiriciyi,
readonlyiçinde bildirilen yöntemleri geçersiz kılma yöntemlerine de uygulayabilirsiniz: System.Objectpublic readonly override string ToString() => $"({X}, {Y})";özellikler ve dizinciler:
private int counter; public int Counter { readonly get => counter; set => counter = value; }Değiştiriciyi bir özelliğin veya dizinlandırıcının her iki erişimcisi için de uygulamanız gerekirse, özelliğin veya dizinlandırıcının
readonlybildiriminde bunu uygulayabilirsiniz.Not
Derleyici, bir özellik bildiriminde değiştiricinin varlığına bakılmaksızın, otomatik uygulanan bir
getreadonlyreadonlyözelliğin erişimcisini olarak bildirmektedir.C# 9.0 ve üzerinde, değiştiriciyi bir erişimci ile bir
readonlyözeliğine veya dizinleştiriciyeinituygulayabilirsiniz:public readonly double X { get; init; }
Değiştiriciyi bir yapı readonly türünün statik üyelerine uygulaya yoktur.
Derleyici, performans iyileştirmeleri readonly için değiştiriciyi kullanabilir. Daha fazla bilgi için bkz. Güvenli ve verimli C# kodu yazma.
Yıkıcılık yok
C# 10'dan itibaren, with belirtilen özelliklere ve alanlara sahip bir yapı türü örneğinin kopyasını üretmek için ifadesini kullanabilirsiniz. Aşağıdaki örnekte de olduğu gibi, hangi üyelerin değiştirileri ve yeni değerlerini belirtmek için nesne başlatıcı söz dizimi kullanırsınız:
public readonly struct Coords
{
public Coords(double x, double y)
{
X = x;
Y = y;
}
public double X { get; init; }
public double Y { get; init; }
public override string ToString() => $"({X}, {Y})";
}
public static void Main()
{
var p1 = new Coords(0, 0);
Console.WriteLine(p1); // output: (0, 0)
var p2 = p1 with { X = 3 };
Console.WriteLine(p2); // output: (3, 0)
var p3 = p1 with { X = 1, Y = 4 };
Console.WriteLine(p3); // output: (1, 4)
}
Yapı türünün tasarımıyla ilgili sınırlamalar
Bir yapı türü tasarlarken, aşağıdaki özel durumlar dışında sınıf türüyle aynı özelliklere sahip oluruz:
Parametresiz oluşturucu bildirilemez. Her yapı türü zaten türün varsayılan değerini üreten örtülü bir parametresiz oluşturucu sağlar.
Not
C# 10'dan başarak, yapı türünde parametresiz bir oluşturucu bildirebilirsiniz. Daha fazla bilgi için Parametresiz oluşturucular ve alan başlatıcıları bölümüne bakın.
Bir örnek alanını veya özelliğini bildiriminde başlatayazabilirsiniz. Ancak, bildiriminde statik veya const alanı ya da statik bir özellik başlatabilirsiniz.
Not
C# 10'dan başarak bildiriminde bir örnek alanı veya özelliği başlatabilirsiniz. Daha fazla bilgi için Parametresiz oluşturucular ve alan başlatıcıları bölümüne bakın.
Yapı türünün oluşturucusu, türün tüm örnek alanlarını başlatmalıdır.
Bir yapı türü, diğer sınıftan veya yapı türünden devralınabilir ve bir sınıfın temeli olamaz. Ancak, bir yapı türü arabirimleri gerçekleştirebilirsiniz.
Yapı türü içinde sonlandırıcı bildiresiniz.
Parametresiz oluşturucular ve alan başlatıcıları
C# 10'dan başarak, aşağıdaki örnekte de olduğu gibi bir yapı türünde parametresiz örnek oluşturucu bildirebilirsiniz:
public readonly struct Measurement
{
public Measurement()
{
Value = double.NaN;
Description = "Undefined";
}
public Measurement(double value, string description)
{
Value = value;
Description = description;
}
public double Value { get; init; }
public string Description { get; init; }
public override string ToString() => $"{Value} ({Description})";
}
public static void Main()
{
var m1 = new Measurement();
Console.WriteLine(m1); // output: NaN (Undefined)
var m2 = default(Measurement);
Console.WriteLine(m2); // output: 0 ()
var ms = new Measurement[2];
Console.WriteLine(string.Join(", ", ms)); // output: 0 (), 0 ()
}
Yukarıdaki örnekte de olduğu gibi, varsayılan değer ifadesi parametresiz bir oluşturucu yok sayar ve tüm değer türü alanlarını varsayılan değerlerine (0 bit deseni) ve tüm başvuru türü alanlarını olarak ayararak üretilen değer olan varsayılan yapı türünü null oluşturur. Yapı türü dizi örneği oluşturma ayrıca parametresiz bir oluşturucu yok sayar ve bir yapı türünün varsayılan değerleriyle doldurulmuş bir dizi üretir.
C# 10'dan itibaren, aşağıdaki örnekte de olduğu gibi bildiriminde bir örnek alanı veya özelliği başlatabilirsiniz:
public readonly struct Measurement
{
public Measurement(double value)
{
Value = value;
}
public Measurement(double value, string description)
{
Value = value;
Description = description;
}
public double Value { get; init; }
public string Description { get; init; } = "Ordinary measurement";
public override string ToString() => $"{Value} ({Description})";
}
public static void Main()
{
var m1 = new Measurement(5);
Console.WriteLine(m1); // output: 5 (Ordinary measurement)
var m2 = new Measurement();
Console.WriteLine(m2); // output: 0 ()
}
Parametresiz bir oluşturucu açıkça bildirilmezse, yapı türü davranışı aşağıdaki gibi olan parametresiz bir oluşturucu sağlar:
Bir yapı türünün açık örnek oluşturucuları varsa veya alan başlatıcısı yoksa, yukarıdaki örnekte de olduğu gibi örtülü parametresiz oluşturucu, alan başlatıcılardan bağımsız olarak bir yapı türünün varsayılan değerini üretir.
Bir yapı türünün açık örnek oluşturucuları yoksa ve alan başlatıcıları varsa, derleyici aşağıdaki örnekte olduğu gibi belirtilen alan başlatmalarını gerçekleştiren bir genel parametresiz oluşturucu sentezler:
public struct Coords { public double X = double.NaN; public double Y = double.NaN; public override string ToString() => $"({X}, {Y})"; } public static void Main() { var p1 = new Coords(); Console.WriteLine(p1); // output: (NaN, NaN) var p2 = default(Coords); Console.WriteLine(p2); // output: (0, 0) var ps = new Coords[3]; Console.WriteLine(string.Join(", ", ps)); // output: (0, 0), (0, 0), (0, 0) }
Yukarıdaki örnekte de olduğu gibi, varsayılan değer ifadesi ve dizi örneği alan başlatıcılarını yoksayar.
Daha fazla bilgi için Bkz. Parametresiz yapı oluşturucuları özellik teklifi notu.
Yapı türünün örneği
C# içinde, kullanılamadan önce bildirilen bir değişkeni başlatmalısiniz. Bir yapı türü değişkeni olamaz (null değere sahip bir değer türünde bir değişken olmadığı sürece), karşılık gelen türün bir örneğini null örneği oluşturmalı. Bunu yapmak için çeşitli yollar vardır.
Genellikle, işleciyle uygun bir oluşturucu çağırarak bir yapı türü örneği new oluştururuz. Her yapı türünün en az bir oluşturucusu vardır. Bu, türün varsayılan değerini üreten örtülü bir parametresiz oluşturucudur. Bir türün varsayılan değerini üretmek için varsayılan değer ifadesi de kullanabilirsiniz.
Bir yapı türünün tüm örnek alanlarına erişilebilirse, bunu işleci olmadan da örnek hale de new ebilirsiniz. Bu durumda, örneğin ilk kullanımı öncesinde tüm örnek alanlarını başlatmalısiniz. Aşağıdaki örnekte bunun nasıl gerçekleştirll olduğu gösterir:
public static class StructWithoutNew
{
public struct Coords
{
public double x;
public double y;
}
public static void Main()
{
Coords p;
p.x = 3;
p.y = 4;
Console.WriteLine($"({p.x}, {p.y})"); // output: (3, 4)
}
}
Yerleşik değer türlerinde, türünbir değerini belirtmek için karşılık gelen değişmez değerleri kullanın.
Başvuruya göre yapı türü değişkenlerini geçirme
Bir yapı türü değişkenini bir yönteme bağımsız değişken olarak iletir veya bir yöntemden yapı türü değeri getirebilirsiniz; yapı türünün tüm örneği kopyalanır. Bu, büyük yapı türleri içeren yüksek performanslı senaryolarda kodunuzun performansını etkileyebilir. Başvuruya göre bir yapı türü değişkeni geçerek değer kopyalamayı önleysiniz. Bir bağımsız ref out değişkenin in başvuruyla geçirilmesi gerektiğini belirtmek için , veya yöntem parametresi değiştiricilerini kullanın. Başvuruya göre bir yöntem sonucu döndüren başvuru dönüşlerini kullanın. Daha fazla bilgi için bkz. Güvenli ve verimli C# kodu yazma.
ref Yapı
C# 7.2'den itibaren, bir yapı ref türünün bildiriminde değiştiricisini kullanabilirsiniz. Yapı türünün ref örnekleri yığında ayrılır ve yönetilen yığına kaçamaz. Derleyici, yapı türlerinin kullanımını aşağıdaki gibi ref sınırlar:
refYapı, bir dizinin öğe türü değildir.refYapı, bir sınıfın veya yapı dışı bir alanın bildirilen bir türürefolabilir.- Yapı,
refarabirimleri uygulayamaz. - Bir
refyapı veya için kutu System.ValueType System.Object edilemez. - Yapı,
reftür bağımsız değişkeni olarak yer alamaz. - Yapı
refdeğişkeni, lambda ifadesi veya yerel bir işlev tarafından yakalanamaz. - Bir
refstruct değişkeni birasyncyöntemde kullanılamaz. Ancak,refYapı değişkenlerini, örneğin veya döndüren zaman uyumlu yöntemlerle kullanabilirsiniz Task Task<TResult> . - Bir
refstruct değişkeni yineleyicileriçinde kullanılamaz.
Genellikle, ref Yapı türlerinin veri üyelerini de içeren bir türe ihtiyacınız olduğunda bir struct türü tanımlarsınız ref :
public ref struct CustomRef
{
public bool IsValid;
public Span<int> Inputs;
public Span<int> Outputs;
}
Bir yapıyı olarak bildirmek için, ref readonly readonly ref tür bildiriminde ve değiştiricilerini birleştirin (değiştiricinin readonly değiştiricisinden önce gelmesi gerekir ref ):
public readonly ref struct ConversionRequest
{
public ConversionRequest(double rate, ReadOnlySpan<double> values)
{
Rate = rate;
Values = values;
}
public double Rate { get; }
public ReadOnlySpan<double> Values { get; }
}
.NET ' te, bir ref struct örnekleri ve ' dir System.Span<T> System.ReadOnlySpan<T> .
struct kısıtlaması
Ayrıca, struct bir tür parametresinin null yapılamayan bir değer türü olduğunu belirtmek için struct kısıtlamadaki anahtar sözcüğünü kullanırsınız. Hem yapı hem de numaralandırma türleri struct kısıtlamayı karşılar.
Dönüşümler
Herhangi bir yapı türü için ( ref Yapı türleri hariç), ve türlerinden ve türlerine bir paketleme ve kutudan çıkarma dönüştürmeleri mevcuttur System.ValueType System.Object . Ayrıca, yapı türü ve uyguladığı herhangi bir arabirim arasında kutulama ve kutudan çıkarma dönüştürmeleri de mevcuttur.
C# dili belirtimi
Daha fazla bilgi için C# dil belirtiminin yapılar bölümüne bakın.
C# 7,2 ve üzeri sürümlerde sunulan özellikler hakkında daha fazla bilgi için aşağıdaki özellik teklifi notlarına bakın:
- ReadOnly yapılar
- Salt okunur örnek üyeleri
- Başvuru benzeri türler ile derleme zamanı güvenliği
- Parametresiz struct oluşturucuları
withYapılarda ifadeye izin ver