Aracılığıyla paylaş


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çinbelirtimleri makalesinde bulabilirsiniz.

Ö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 structve record structgibi 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 publicolarak 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 unsafeolarak bildirilebilir. Oluşturucular partialolamaz.

Alan başlatıcıları yürütme

Örnek değişkeni başlatıcıları (§15.11.3) aşağıdaki gibi değiştirilir:

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şturucusununvarsayı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_initializertarafı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ı nullolarak 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 : structise 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ı