Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
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ında belirtilmiştir.
Özellik belirtimlerini C# dil standardına benimseme işlemi hakkında daha fazla bilgi edinmek için belirtimleri makalesinde bulabilirsiniz.
Şampiyon sorunu: https://github.com/dotnet/csharplang/issues/4334
Kayıt yapısının söz dizimi aşağıdaki gibidir:
record_struct_declaration
: attributes? struct_modifier* 'partial'? 'record' 'struct' identifier type_parameter_list?
parameter_list? struct_interfaces? type_parameter_constraints_clause* record_struct_body
;
record_struct_body
: struct_body
| ';'
;
Kayıt yapısı türleri, diğer yapı türleri gibi değer türleridir. Onlar örtülü olarak System.ValueType
sınıfından devralır.
Kayıt yapısının değiştiricileri ve üyeleri, yapılarla aynı kısıtlamalara tabidir (türdeki erişilebilirlik, üyelerde değiştiriciler, base(...)
örnek oluşturucu başlatıcıları, oluşturucudaki this
için kesin atama, yıkıcılar, ...). Kayıt yapıları, parametresiz örnek oluşturucuları ve alan başlatıcıları için yapılarla aynı kuralları da izler, ancak bu belgede yapılar için bu kısıtlamaları genel olarak kaldıracağımız varsayılır.
Bkz. §16.4.9parametresiz yapı oluşturucuları belirtimi.
Kayıt yapıları ref
değiştiriciyi kullanamaz.
Bir kısmi kayıt yapısının kısmi tür bildirimlerinden en fazla biri parameter_list
sağlayabilir.
parameter_list
boş olabilir.
Kayıt yapısı parametreleri ref
, out
veya this
değiştiricileri kullanamaz (ancak in
ve params
izin verilir).
Kayıt yapısının üyeleri
Kayıt yapısı gövdesinde bildirilen üyelere ek olarak, bir kayıt yapısı türü ek sentezlenmiş üyelere sahiptir. Kayıt yapısı gövdesinde "eşleşen" imzaya sahip bir üye bildirilmediği veya "eşleşen" imzaya sahip erişilebilir somut sanal olmayan bir üye devralınmadığı sürece üyeler sentezlenir. İki üye, aynı imzaya sahipse veya devralma senaryosunda "gizlendiği" kabul edilirse eşleşen olarak kabul edilir. Bkz. İmzalar ve aşırı yüklenme §7.6. Bir kayıt yapısının üyesinin "Clone" olarak adlandırılması hatadır.
Bir kayıt yapısının örnek alanının güvenli olmayan bir türe sahip olması hatadır.
Kayıt yapısının bir sonlandırıcı tanımlamasına izin verilmez.
Sentezlenen üyeler aşağıdaki gibidir:
Eşitlik üyeleri
Sentezlenen eşitlik üyeleri bir kayıt sınıfındakine benzer (bu tür içinEquals
, Equals
türü için object
, bu tür için ==
ve !=
işleçleri),
EqualityContract
eksikliği dışında null denetimleri veya kalıtım.
Kayıt yapısı, System.IEquatable<R>
'ı uygular ve kayıt yapısı olan Equals(R other)
'nin, R
için sentezlenmiş güçlü türde bir aşırı yüklemesini içerir.
yöntemi public
.
yöntemi açıkça bildirilebilir. Açık bildirim beklenen imza veya erişilebilirlikle eşleşmiyorsa bu bir hatadır.
Equals(R other)
kullanıcı tanımlıysa (sentezlenmediyse) ancak GetHashCode
değilse, bir uyarı oluşturulur.
public readonly bool Equals(R other);
Sentezlenmiş Equals(R)
, ancak ve ancak, kayıt yapısındaki her bir örnek alan true
'nin fieldN
alan türündeki System.Collections.Generic.EqualityComparer<TN>.Default.Equals(fieldN, other.fieldN)
değerinin TN
olması durumunda true
döndürür.
Kayıt yapısı, aşağıdaki gibi bildirilen işleçlere eşdeğer sentezlenmiş ==
ve !=
işleçleri içerir:
public static bool operator==(R r1, R r2)
=> r1.Equals(r2);
public static bool operator!=(R r1, R r2)
=> !(r1 == r2);
Equals
işleci tarafından çağrılan ==
yöntemi, yukarıda belirtilen Equals(R other)
yöntemidir.
!=
işleci ==
işlemcisine yetki verir. İşleçler açıkça bildirilirse bu bir hatadır.
Kayıt yapısı, aşağıdaki gibi bildirilen bir yönteme eşdeğer olan otomatik oluşturulmuş bir geçersiz kılma yöntemi içerir.
public override readonly bool Equals(object? obj);
Geçersiz kılma açıkça bildirildiğinde bu bir hatadır.
Sentezlenen geçersiz kılma, other is R temp && Equals(temp)
bir kayıt yapısı olduğunda R
döndürür.
Kayıt yapısı, aşağıdaki gibi bildirilen bir yönteme eşdeğer olan otomatik oluşturulmuş bir geçersiz kılma yöntemi içerir.
public override readonly int GetHashCode();
yöntemi açıkça bildirilebilir.
Equals(R)
ve GetHashCode()
'den biri açıkça deklar edilir ancak diğeri açıkça deklar edilmemişse bir uyarı bildirilir.
GetHashCode()
sentezlenmiş geçersiz kılma, int
her örnek alanı için System.Collections.Generic.EqualityComparer<TN>.Default.GetHashCode(fieldN)
değerlerini fieldN
'ın TN
türü olduğu durumda birleştirerek fieldN
sonucunu verir.
Örneğin, aşağıdaki kayıt yapısını göz önünde bulundurun:
record struct R1(T1 P1, T2 P2);
Bu kayıt yapısı için, otomatik olarak oluşturulan eşitlik üyeleri şöyle olacaktır:
struct R1 : IEquatable<R1>
{
public T1 P1 { get; set; }
public T2 P2 { get; set; }
public override bool Equals(object? obj) => obj is R1 temp && Equals(temp);
public bool Equals(R1 other)
{
return
EqualityComparer<T1>.Default.Equals(P1, other.P1) &&
EqualityComparer<T2>.Default.Equals(P2, other.P2);
}
public static bool operator==(R1 r1, R1 r2)
=> r1.Equals(r2);
public static bool operator!=(R1 r1, R1 r2)
=> !(r1 == r2);
public override int GetHashCode()
{
return Combine(
EqualityComparer<T1>.Default.GetHashCode(P1),
EqualityComparer<T2>.Default.GetHashCode(P2));
}
}
Yazdırma üyeleri: PrintMembers ve ToString yöntemleri
Kayıt yapısı, aşağıdaki gibi bildirilen bir yönteme eşdeğer bir sentezlenmiş yöntem içerir:
private bool PrintMembers(System.Text.StringBuilder builder);
yöntemi aşağıdakileri yapar:
- kayıt yapısının yazdırılabilir her bir üyesi için (statik olmayan ortak alanlar ve okunabilir özellik üyeleri), o üyenin adını, ardından " = ", ve üyenin değerini ekler ve bunları ", " ile ayırır.
- kayıt yapısı yazdırılabilir üyelere sahipse 'doğru' değerini döndürür.
Değer türüne sahip bir üye için, hedef platformda kullanılabilen en verimli yöntemi kullanarak değerini dize gösterimine dönüştüreceğiz. Şu anda bu, ToString
'e geçmeden önce StringBuilder.Append
'ı çağırmak anlamına gelir.
Kaydın yazdırılabilir üyeleri,readonly
get
olmayan bir erişimciye sahip okunabilir bir özellik içermiyorsa, sentezlenen PrintMembers
readonly
olur. Kaydın alanlarının readonly
olması, PrintMembers
yönteminin readonly
olması için gerekli değildir.
PrintMembers
yöntemi açıkça bildirilebilir.
Açık bildirim beklenen imza veya erişilebilirlikle eşleşmiyorsa bu bir hatadır.
Kayıt yapısı, aşağıdaki gibi bildirilen bir yönteme eşdeğer bir sentezlenmiş yöntem içerir:
public override string ToString();
Kayıt yapısının PrintMembers
yöntemi readonly
ise, sentezlenen ToString()
yöntemi readonly
olur.
yöntemi açıkça bildirilebilir. Açık bildirim beklenen imza veya erişilebilirlikle eşleşmiyorsa bu bir hatadır.
Sentezlenen yöntem:
- bir
StringBuilder
örneği oluşturur, - kayıt yapısı adını oluşturucuya ekler ve ardından " { ",
- kayıt yapısının
PrintMembers
yöntemini çağırarak oluşturucuyu verir ve ardından " " " true döndürdüyse, - ekler "}",
-
builder.ToString()
ile yapıcının içeriğini döndürür.
Örneğin, aşağıdaki kayıt yapısını göz önünde bulundurun:
record struct R1(T1 P1, T2 P2);
Bu kayıt yapısı için, sentezlenen yazdırma üyeleri şöyle olabilir:
struct R1 : IEquatable<R1>
{
public T1 P1 { get; set; }
public T2 P2 { get; set; }
private bool PrintMembers(StringBuilder builder)
{
builder.Append(nameof(P1));
builder.Append(" = ");
builder.Append(this.P1); // or builder.Append(this.P1.ToString()); if P1 has a value type
builder.Append(", ");
builder.Append(nameof(P2));
builder.Append(" = ");
builder.Append(this.P2); // or builder.Append(this.P2.ToString()); if P2 has a value type
return true;
}
public override string ToString()
{
var builder = new StringBuilder();
builder.Append(nameof(R1));
builder.Append(" { ");
if (PrintMembers(builder))
builder.Append(" ");
builder.Append("}");
return builder.ToString();
}
}
Konum kayıt yapısı üyeleri
Yukarıdaki üyelere ek olarak, parametre listesi ("konumsal kayıtlar") içeren kayıt yapıları, yukarıdaki üyelerle aynı koşullara sahip ek üyeleri sentezler.
Temel Yapıcı
Kayıt yapısı, imzası tür bildiriminin değer parametrelerine karşılık gelen bir ortak oluşturucuya sahiptir. Bu, tür için birincil oluşturucu olarak adlandırılır. Birincil oluşturucunun ve yapıda aynı imzaya sahip bir oluşturucunun zaten mevcut olması bir hatadır. Tür bildirimi bir parametre listesi içermiyorsa, birincil oluşturucu oluşturulmaz.
record struct R1
{
public R1() { } // ok
}
record struct R2()
{
public R2() { } // error: 'R2' already defines constructor with same parameter types
}
Bir kayıt yapısı için örnek alanı bildirimlerinin değişken başlatıcıları içermesine izin verilir. Birincil oluşturucu yoksa, örnek başlatıcıları parametresiz oluşturucunun bir parçası olarak yürütülür. Aksi takdirde, çalışma zamanında birincil oluşturucu kayıt yapısı gövdesinde görünen örnek başlatıcılarını yürütür.
Bir kayıt yapısı birincil oluşturucuya sahipse, kullanıcı tanımlı oluşturucuların birincil oluşturucuyu veya açıkça bildirilen bir oluşturucuyu çağıran açık bir this
oluşturucu başlatıcısı olmalıdır.
Birincil oluşturucunun ve kayıt yapısının üyelerinin parametreleri, örnek alanlarının veya özelliklerinin başlatıcıları içinde kapsam içindedir. Örnek üyeleri bu konumlarda bir hata olabilir (örnek üyelerinin bugün normal oluşturucu başlatıcılarında kapsamda yer almalarına benzer, ancak kullanılması gereken bir hatadır), ancak birincil oluşturucunun parametreleri kapsam içinde ve kullanılabilir olur ve üyeleri gölgeler. Statik üyeler de kullanılabilir.
Birincil oluşturucunun parametresi okunmazsa bir uyarı oluşturulur.
Yapı örneği oluşturucuları için kesin atama kuralları, kayıt yapılarının birincil oluşturucusna uygulanır. Örneğin, aşağıdaki bir hatadır:
record struct Pos(int X) // definite assignment error in primary constructor
{
private int x;
public int X { get { return x; } set { x = value; } } = X;
}
Özellikler
Kayıt yapısı bildiriminin her kayıt yapısı parametresi için, adı ve türü değer parametresi bildiriminden alınan ilgili ortak özellik üyesi vardır.
Kayıt yapısı için:
- Kayıt yapısında
get
değiştirici varsa, genelinit
vereadonly
otomatik özelliği oluşturulur, aksi takdirdeget
veset
. Her iki tür küme erişimcisi (set
veinit
) "eşleştirme" olarak kabul edilir. Bu nedenle kullanıcı, sentezlenmiş değiştirilebilir bir özellik yerine yalnızca init özelliğini bildirebilir. Eşleşen türe sahip devralınanabstract
özelliği geçersiz kılınır. Kayıt yapısının, beklenen ada ve türe sahip bir örnek alanı varsa otomatik özellik oluşturulmaz. Devralınan özelliğinpublic
get
veset
/init
erişimcileri yoksa bu bir hatadır. Devralınan özellik veya alan gizliyse bu bir hatadır.
Otomatik özellik, eşdeğer birincil oluşturucu parametresinin başlangıç değerine ayarlanır. Öznitelikler, sırasal olarak ilgili kayıt yapısı parametresine uygulanmış öznitelikler içinproperty:
veyafield:
hedefleri kullanılarak, sentezlenen otomatik özelliğe ve onun destek alanına uygulanabilir.
Parçalarına ayır
En az bir parametreye sahip konumsal kayıt yapısı, birincil oluşturucu bildiriminin her parametresi için out parametre bildirimiyle Deconstruct
adlı genel bir void-dönüş örneği yöntemini sentezler. Deconstruct yönteminin her parametresi, birincil oluşturucu bildiriminin karşılık gelen parametresiyle aynı türe sahiptir. Yöntem gövdesi, Deconstruct yönteminin her bir parametresini, aynı ada sahip bir üyeye, bir örnek üyesi erişiminden elde edilen değere atar.
Gövdede erişilen örnek üyeler arasındareadonly
get
olmayan bir erişimciye sahip bir özellik yoksa, sentezlenen Deconstruct
yöntemi readonly
olur.
yöntemi açıkça bildirilebilir. Açık bildirimin beklenen imza veya erişilebilirlikle eşleşmemesi veya statik olması bir hatadır.
Yapılarda with
ifadesine izin ver
Artık with
ifadesindeki alıcının yapı türüne sahip olması geçerlidir.
with
ifadesinin sağ tarafında, alıcı türüne ait erişilebilir bir örnek alanı veya özellik olması gereken member_initializer_list
'e bir atama dizisi içeren bir bulunmaktadır.
Yapı türünden bir alıcı için, alıcı önce kopyalanır, ardından her member_initializer
, dönüştürme sonucunun bir alan veya özellik erişimi ataması gibi aynı şekilde işlenir.
Atamalar alfabetik sırayla işlenir.
Kayıtlarda iyileştirmeler
record class
izin ver
Kayıt türleri için mevcut söz dizimi, record class
ile aynı anlama sahip olan record
'yi sağlar.
record_declaration
: attributes? class_modifier* 'partial'? 'record' 'class'? identifier type_parameter_list?
parameter_list? record_base? type_parameter_constraints_clause* record_body
;
Kullanıcı tanımlı pozisyon tabanlı üyelerin alan olarak kullanılmasını sağlama
Beklenen ad ve türe sahip bir örnek alan kayıtta varsa veya devralınmışsa, otomatik özellik oluşturulmaz.
Yapılarda parametresiz oluşturuculara ve üye başlatıcılara izin ver
Bkz. parametresiz yapı oluşturucuları özelliği.
Açık sorular
- meta verilerdeki kayıt yapılarını tanıma (Yararlanabileceğimiz gizli bir klon yöntemi yok...)
Yanıtladı
- PrintMembers tasarımını korumak istediğimizi onaylayın (
bool
döndüren ayrı yöntem ) (yanıt: evet) -
record ref struct
izin vermeyacağımızı onaylayın (IEquatable<RefStruct>
ve başvuru alanlarıyla ilgili sorun) (yanıt: evet) - eşitlik üyelerinin uygulanmasını onaylayın. Alternatif olarak,
bool Equals(R other)
sentezlenmişbool Equals(object? other)
ve işleçlerin tümü yalnızcaValueType.Equals
için temsilcidir. (yanıt: evet) - birincil oluşturucu olduğunda alan başlatıcılarına izin vermek istediğimizi onaylayın. Biz bu aşamadayken parametresiz yapı oluşturucularına da izin vermek istiyor muz (Activator sorunu görünüşe göre düzeltildi)? (yanıt: evet, güncellenmiş spesifikasyon LDM'de gözden geçirilmelidir)
-
Combine
yöntemi hakkında ne kadar söylemek istiyoruz? (yanıt: mümkün olduğunca az) - Kopya oluşturucu imzası olan kullanıcı tanımlı bir oluşturucuya izin vermemeli miyiz? (yanıt: hayır, kayıt yapılarında kopya oluşturucu belirtimi yoktur)
- "Clone" adlı üyeleri reddetmek istediğimizi onaylayın. (yanıt: doğru)
- sentezlenmiş
Equals
mantığının, çalışma zamanı uygulamasıyla (örn. float.NaN) işlevsel olarak eşdeğer olup olmadığını bir kez daha denetleyin. (yanıt: LDM'de onaylandı) - alan veya özellik hedefleme öznitelikleri konumsal parametre listesine yerleştirilebilir mi? (yanıt: evet, kayıt sınıfı için olduğu gibi)
- Generiklerde
with
? (yanıt: C# 10 için kapsam dışında) -
GetHashCode
,record struct S1;
ilerecord struct S2;
arasında farklı değerler elde etmek için kendi türünün bir karmasını içermeli mi? (yanıt: hayır)
C# feature specifications