Parametresiz yapı oluşturucuları
Not
Bu makale bir özellik belirtimidir. Belirtim, özelliğin tasarım belgesi olarak görev alır. Önerilen belirtim değişikliklerini ve özelliğin tasarımı ve geliştirilmesi sırasında gereken bilgileri içerir. Bu makaleler, önerilen belirtim değişiklikleri son haline getirilene ve geçerli ECMA belirtimine dahil edilene kadar yayımlanır.
Özellik belirtimi ile tamamlanan uygulama arasında bazı tutarsızlıklar olabilir. Bu farklılıklar, ilgili dil tasarım toplantısı (LDM) notlarındakaydedilir.
Özellik belirtimlerini C# dil standardına benimseme işlemi hakkında daha fazla bilgi edinmek için
Özet
Yapı türleri için parametresiz oluşturucuları ve örnek alanı başlatıcılarını destekler.
Motivasyon
Açık parametresiz oluşturucular, yapı türünün en az şekilde yapılandırılmış örnekleri üzerinde daha fazla denetim sağlar.
Örnek alanı başlatıcıları, birden çok oluşturucu arasında basitleştirilmiş başlatmaya izin verir.
Bunlar birlikte struct
ve class
bildirimleri arasındaki belirgin bir boşluğu kapatır.
Alan başlatıcıları desteği, birincil oluşturucuyu açıkça uygulamadan record struct
bildirimlerinde alanların başlatılmasına da olanak sağlar.
record struct Person(string Name)
{
public object Id { get; init; } = GetNextId();
}
Yapı alanı başlatıcıları parametreleri olan oluşturucular için destekleniyorsa, bunu parametresiz oluşturuculara da genişletmek doğal görünür.
record struct Person()
{
public string Name { get; init; }
public object Id { get; init; } = GetNextId();
}
Teklif
Örnek alanı başlatıcıları
Bir yapı için örnek alanı bildirimleri başlatıcıları içerebilir.
Sınıf alanı başlatıcılarında olduğu gibi §15.5.6.3:
Örnek alanı için değişken başlatıcı, oluşturulan örneğe başvuramaz.
Bir yapıda alan başlatıcıları varsa ve alan başlatıcıları çalıştırılmayacağı için bildirilen örnek oluşturucu yoksa bir hata bildirilir.
struct S { int F = 42; } // error: 'struct' with field initializers must include an explicitly declared constructor
Kurucular
Bir yapı parametresiz örnek oluşturucu bildirebilir.
Parametresiz örnek oluşturucu, struct
, readonly struct
, ref struct
ve record struct
gibi tüm yapı türleri için geçerlidir.
Parametresiz bir örnek oluşturucu bildirilmezse, yapı (bkz. §16.4.9) ...
örtük olarak, her zaman tüm değer türü alanlarını varsayılan değerlerine ve tüm başvuru türü alanlarını null olarak ayarlamanın sonucunda elde edilen değeri döndüren parametresiz bir örnek oluşturucuya sahiptir.
Değiştiriciler
Parametresiz bir örnek yapı oluşturucu public
olarak bildirilmelidir.
struct S0 { } // ok
struct S1 { public S1() { } } // ok
struct S2 { internal S2() { } } // error: parameterless constructor must be 'public'
Meta verilerden türler içeri aktarılırken genel olmayan oluşturucular yoksayılır.
Oluşturucular extern
veya unsafe
olarak bildirilebilir.
Oluşturucular partial
olamaz.
Alan başlatıcıları yürütme
bir sınıf örnekleyici kurucusunun kurucu başlatıcısı yoksa veya
base(...)
formunun bir kurucu başlatıcısı varsa, bu kurucu, sınıfında tanımlanan örnek alanları için variable_initializertarafından belirtilen başlatmaları örtük olarak yapar. Bu, oluşturucuya girdikten hemen sonra ve doğrudan temel sınıf oluşturucusunun örtük çağrısı yapılmadan önce yürütülen atama dizisine karşılık gelir.Struct yapısının örnek oluşturucusu bir oluşturucu başlatıcısına sahip olmadığında, struct içinde bildirilen örnek alanlarının variable_initializertarafından belirtilen başlatmalarını otomatik olarak yapar. Bu, oluşturucuya girdikten hemen sonra yürütülen atama dizisine karşılık gelir.
Yapı örneği oluşturucusunun
varsayılan parametresiz oluşturucuyu temsil eden bir oluşturucu başlatıcısı olduğunda, bildirilen oluşturucu tüm örnek alanlarını örtük olarak temizler ve yapısında bildirilen örnek alanlarının variable_initializer tarafından belirtilen başlatmaları gerçekleştirir. Oluşturucuya girdikten hemen sonra, tüm değer türü alanları varsayılan değerlerine ve tüm başvuru türü alanlarınull
olarak ayarlanır. Bundan hemen sonra, değişken_başlatıcı'lere karşılık gelen bir atama dizisi yürütülür.
Kesin atama
Örnek alanları (fixed
alanları dışında) kesinlikle this()
başlatıcısı olmayan yapı örneği oluşturucularında atanmalıdır (bkz. §16.4.9).
struct S0 // ok
{
int x;
object y;
}
struct S1 // error: 'struct' with field initializers must include an explicitly declared constructor
{
int x = 1;
object y;
}
struct S2
{
int x = 1;
object y;
public S2() { } // error in C# 10 (valid starting in C# 11): field 'y' must be assigned
}
struct S3 // ok
{
int x = 1;
object y;
public S3() { y = 2; }
}
base()
başlatıcı yok
Yapı oluşturucularında base()
başlatıcıya izin verilmiyor.
Derleyici, yapı örneği oluşturucularından temel System.ValueType
oluşturucuya bir çağrı yaymaz.
record struct
Bir hata bildirilir eğer bir record struct
'ın alan başlatıcıları varsa ve ne birincil oluşturucu ne de herhangi bir örnek oluşturucu içermiyorsa zira bu durumda alan başlatıcıları çalıştırılmayacaktır.
record struct R0; // ok
record struct R1 { int F = 42; } // error: 'struct' with field initializers must include an explicitly declared constructor
record struct R2() { int F = 42; } // ok
record struct R3(int F); // ok
Boş parametre listesi olan bir record struct
parametresiz birincil oluşturucuya sahip olur.
record struct R3(); // primary .ctor: public R3() { }
record struct R4() { int F = 42; } // primary .ctor: public R4() { F = 42; }
Bir record struct
açık parametresiz oluşturucu birincil oluşturucuyu veya açıkça bildirilen bir oluşturucuyu çağıran bir this
başlatıcıya sahip olmalıdır.
record struct R5(int F)
{
public R5() { } // error: must have 'this' initializer that calls explicit .ctor
public R5(object o) : this() { } // ok
public int F = F;
}
Alanları
Örtük olarak tanımlanmış parametresiz oluşturucu, alan türleri için parametresiz oluşturucuları çağırmak yerine alanları sıfırlar. Alan yapıcılarının yoksayıldığına dair hiçbir uyarı bildirilmez. C#9'dan değişiklik yok.
struct S0
{
public S0() { }
}
struct S1
{
S0 F; // S0 constructor ignored
}
struct S<T> where T : struct
{
T F; // constructor (if any) ignored
}
default
ifadesi
default
parametresiz oluşturucuyu yoksayar ve sıfırlanmış bir örnek oluşturur.
C#9'dan değişiklik yok.
// struct S { public S() { } }
_ = default(S); // constructor ignored, no warning
new()
Nesne oluşturma, ortaksa parametresiz oluşturucuyu çağırır; aksi takdirde örnek sıfırlanır. C#9'dan değişiklik yok.
// public struct PublicConstructor { public PublicConstructor() { } }
// public struct PrivateConstructor { private PrivateConstructor() { } }
_ = new PublicConstructor(); // call PublicConstructor::.ctor()
_ = new PrivateConstructor(); // initobj PrivateConstructor
Bir uyarı dalgası, oluşturucuları olan ancak parametresiz oluşturucu içermeyen bir yapı türüyle new()
kullanımı için bir uyarı bildirebilir.
new()
veya struct
kısıtlaması olan bir tür parametresi yerine böyle bir yapı türü kullanıldığında uyarı bildirilmeyecektir.
struct S { public S(int i) { } }
static T CreateNew<T>() where T : new() => new T();
_ = new S(); // no warning called
_ = CreateNew<S>(); // ok
Başlatılmamış değerler
Açıkça başlatılmayan bir yapı türünün yerel bir değişkeni veya alanı sıfırlanır. Derleyici, boş olmayan başlatılmamış bir yapı için belirli bir atama hatası bildirir. C#9'dan değişiklik yok.
NoConstructor s1;
PublicConstructor s2;
s1.ToString(); // error: use of unassigned local (unless type is empty)
s2.ToString(); // error: use of unassigned local (unless type is empty)
Dizi ayırma
Dizi ayırma parametresiz oluşturucuları yoksayar ve sıfırlanmış öğeler oluşturur. C#9'dan değişiklik yok.
// struct S { public S() { } }
var a = new S[1]; // constructor ignored, no warning
Parametre varsayılan değeri new()
new()
parametresinin varsayılan değeri, ortaksa parametresiz oluşturucuya bağlanır (ve değerin sabit olmadığını bildiren bir hata bildirir); aksi takdirde örnek sıfırlanır.
C#9'dan değişiklik yok.
// public struct PublicConstructor { public PublicConstructor() { } }
// public struct PrivateConstructor { private PrivateConstructor() { } }
static void F1(PublicConstructor s1 = new()) { } // error: default value must be constant
static void F2(PrivateConstructor s2 = new()) { } // ok: initobj
Tür parametresi kısıtlamaları: new()
ve struct
new()
ve struct
türü parametre kısıtlamaları tanımlandığında parametresiz oluşturucunun public
olmasını gerektirir (bkz. Kısıtlamaları karşılama - §8.4.5).
Derleyici, tüm yapıların new()
ve struct
kısıtlamaları karşılar olduğunu varsayar.
C#9'dan değişiklik yok.
// public struct PublicConstructor { public PublicConstructor() { } }
// public struct InternalConstructor { internal InternalConstructor() { } }
static T CreateNew<T>() where T : new() => new T();
static T CreateStruct<T>() where T : struct => new T();
_ = CreateNew<PublicConstructor>(); // ok
_ = CreateStruct<PublicConstructor>(); // ok
_ = CreateNew<InternalConstructor>(); // compiles; may fail at runtime
_ = CreateStruct<InternalConstructor>(); // compiles; may fail at runtime
new T()
System.Activator.CreateInstance<T>()
çağrısı olarak gönderilir ve derleyici, CreateInstance<T>()
uygulamasının tanımlandığı takdirde parametresiz public
oluşturucuyu çağırdığı varsayılır.
.NET Framework ile Activator.CreateInstance<T>()
, kısıtlama where T : new()
ise parametresiz oluşturucuyu çağırır, ancak kısıtlama where T : struct
ise parametresiz oluşturucuyu yoksayar gibi görünür.
İsteğe bağlı parametreler
İsteğe bağlı parametrelere sahip oluşturucular parametresiz oluşturucular olarak kabul edilmez. C#9'dan değişiklik yok.
struct S1 { public S1(string s = "") { } }
struct S2 { public S2(params object[] args) { } }
_ = new S1(); // ok: ignores constructor
_ = new S2(); // ok: ignores constructor
Meta veriler
Açık parametresiz yapı örneği oluşturucuları meta veriye gönderilir.
Genel parametresiz yapı örneği oluşturucuları meta verilerden içeri aktarılacak; genel olmayan yapı örneği oluşturucuları yoksayılır. C#9'dan değişiklik yok.
Ayrıca bkz.
Tasarım toplantıları
- https://github.com/dotnet/csharplang/blob/main/meetings/2021/LDM-2021-04-28.md#open-questions-in-record-and-parameterless-structs
- https://github.com/dotnet/csharplang/blob/main/meetings/2021/LDM-2021-03-10.md#parameterless-struct-constructors
- https://github.com/dotnet/csharplang/blob/main/meetings/2021/LDM-2021-01-27.md#field-initializers
C# feature specifications