16 Yapı
16.1 Genel
Yapılar, veri üyeleri ve işlev üyeleri içerebilen veri yapılarını temsil eden sınıflara benzer. Ancak, sınıflardan farklı olarak yapılar değer türleridir ve yığın ayırma gerektirmez. Bir struct
türün değişkeni doğrudan öğesinin struct
verilerini içerirken, sınıf türündeki bir değişken, ikincisinde nesne olarak bilinen verilere bir başvuru içerir.
Not: Yapılar özellikle değer semantiğine sahip küçük veri yapıları için kullanışlıdır. Karmaşık sayılar, koordinat sistemindeki noktalar veya sözlükteki anahtar-değer çiftlerinin tümü iyi yapı örnekleridir. Bu veri yapılarının anahtarı, çok az veri üyesine sahip olmaları ve devralma veya başvuru semantiği kullanılmasını gerektirmemeleridir; bunun yerine atamanın başvuru yerine değeri kopyaladığı değer semantiği kullanılarak rahatça uygulanabilmesidir. son not
§8.3.5'te açıklandığı gibi, C# tarafından sağlanan , double
ve bool
gibi int
basit türler aslında tüm yapı türleridir.
16.2 Yapı bildirimleri
16.2.1 Genel
struct_declaration, yeni bir yapı bildiren bir type_declaration (§14.7) olur:
struct_declaration
: attributes? struct_modifier* 'ref'? 'partial'? 'struct'
identifier type_parameter_list? struct_interfaces?
type_parameter_constraints_clause* struct_body ';'?
;
struct_declaration isteğe bağlı bir öznitelik kümesi (§22) ve ardından isteğe bağlı bir struct_modifierkümesi (§16.2.2) ve ardından isteğe bağlı ref
değiştirici (§16.2.3) ve ardından isteğe bağlı bir kısmi değiştirici (§15.2.7) ve ardından anahtar sözcüğü struct
ve yapıyı adlandıran bir tanımlayıcıdan oluşur. ardından isteğe bağlı type_parameter_list belirtimi (§15.2.3), ardından isteğe bağlı bir struct_interfaces belirtimi (§16.2.5) ve ardından isteğe bağlı type_parameter_constraints yan tümceleri belirtimi (§15.2.5) ve ardından bir struct_body (§16.2.6) ve isteğe bağlı olarak noktalı virgül.
Bir yapı bildirimi, bir type_parameter_list sağlamadığı sürece bir type_parameter_constraints_clauses sağlamaz.
type_parameter_list sağlayan bir yapı bildirimi genel bir yapı bildirimidir. Ayrıca, genel bir sınıf bildiriminin veya genel bir yapı bildiriminin içinde iç içe yerleştirilmiş herhangi bir yapı kendisi genel bir yapı bildirimidir, çünkü içeren tür için tür bağımsız değişkenleri oluşturulmuş bir tür oluşturmak için sağlanmalıdır (§8.4).
Anahtar sözcük içeren bir ref
yapı bildiriminin struct_interfaces bir parçası olmamalıdır.
16.2.2 Yapı değiştiricileri
struct_declaration isteğe bağlı olarak bir dizi struct_modifieriçerebilir:
struct_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
| 'readonly'
| unsafe_modifier // unsafe code support
;
unsafe_modifier (§23.2) yalnızca güvenli olmayan kodda (§23) kullanılabilir.
Aynı değiştiricinin bir yapı bildiriminde birden çok kez görünmesi derleme zamanı hatasıdır.
readonly
dışında, bir yapı bildiriminin değiştiricileri bir sınıf bildiriminin (§15.2.2) anlamları aynıdır.
Değiştirici, readonly
struct_declaration örnekleri sabit olan bir tür bildirdiğini gösterir.
Salt okunur bir yapı aşağıdaki kısıtlamalara sahiptir:
- Örnek alanlarının her biri de bildirilmelidir
readonly
. - Örnek özelliklerinin hiçbirinin set_accessor_declaration (§15.7.3) yoktur.
- Alan benzeri olaylar bildirmeyecektir (§15.8.2).
Salt okunur bir yapının örneği bir yönteme geçirildiğinde, this
herhangi bir örnek alanına yazma erişimine izin veren bir giriş bağımsız değişkeni/parametresi olarak kabul edilir (oluşturucular hariç).
16.2.3 Başv değiştirici
Değiştirici, ref
struct_declaration örnekleri yürütme yığınında ayrılan bir tür bildirdiğini gösterir. Bu türlere başvuru yapısı türleri adı verilir. Değiştirici ref
, örneklerin başvuru benzeri alanlar içerebileceğini ve güvenli bağlamının dışına kopyalanmayabileceğini bildirir (§16.4.12). Bir başvuru yapısının güvenli bağlamını belirleme kuralları §16.4.12'de açıklanmıştır.
Aşağıdaki bağlamlardan herhangi birinde başvuru yapısı türü kullanılıyorsa derleme zamanı hatasıdır:
- Bir dizinin öğe türü olarak.
- Bir sınıf veya değiştiricisi olmayan
ref
bir yapı alanının bildirilen türü olarak. - veya
System.Object
için kutulanıyorSystem.ValueType
. - Tür bağımsız değişkeni olarak.
- Tanımlama grubu öğesinin türü olarak.
- Zaman uyumsuz bir yöntem.
- Yineleyici.
- Türünden
ref struct
türüne veya türüneobject
System.ValueType
dönüştürme yoktur. - Herhangi bir
ref struct
arabirimi uygulamak için bir tür bildirilmeyecektir. - içinde veya içinde
object
System.ValueType
bildirilen ancak bir türdeki geçersiz kılınmayan birref struct
örnek yöntemi, buref struct
türdeki bir alıcıyla çağrılmaz. - Bir türe ait
ref struct
örnek yöntemi, bir temsilci türüne yöntem grubu dönüştürmesi tarafından yakalanmaz. - Başvuru yapısı bir lambda ifadesi veya yerel bir işlev tarafından yakalanmamalıdır.
Not: Örtük
this
parametre bu bağlamlarda kullanılamadığından, Aref struct
örnek yöntemlerini bildirmezasync
veyayield break
bir veya deyimini kullanmazyield return
. son not
Bu kısıtlamalar, türünde bir değişkenin ref struct
artık geçerli olmayan yığın belleğine veya artık geçerli olmayan değişkenlere başvurmamasını sağlar.
16.2.4 Kısmi değiştirici
Değiştirici, partial
bu struct_declaration kısmi tür bildirimi olduğunu gösterir. Bir kapsayan ad alanı veya tür bildirimi içinde aynı ada sahip birden çok kısmi yapı bildirimi, §15.2.7'de belirtilen kurallara uyarak tek bir yapı bildirimi oluşturmak için birleştirilir.
16.2.5 Yapı arabirimleri
Yapı bildirimi bir struct_interfaces belirtimi içerebilir ve bu durumda yapının verilen arabirim türlerini doğrudan uyguladığı söylenir. Genel tür bildiriminde (§15.3.9.7) bildirilen iç içe yerleştirilmiş bir tür de dahil olmak üzere, yapılandırılmış bir yapı türü için, uygulanan her arabirim türü, verilen arabirimdeki her type_parameter için, yapılandırılmış türün ilgili type_argument değiştirilerek elde edilir.
struct_interfaces
: ':' interface_type_list
;
Kısmi yapı bildiriminin (§15.2.7) birden çok parçasındaki arabirimlerin işlenmesi ,15.2.4.3'te daha ayrıntılı olarak ele alınıyor.
Arabirim uygulamaları §18.6'da daha ayrıntılı olarak ele alınıyor.
16.2.6 Yapı gövdesi
Bir yapının struct_body , yapının üyelerini tanımlar.
struct_body
: '{' struct_member_declaration* '}'
;
16.3 Yapı üyeleri
Bir yapının üyeleri, struct_member_declarationtarafından tanıtılan üyelerden ve türünden System.ValueType
devralınan üyelerden oluşur.
struct_member_declaration
: constant_declaration
| field_declaration
| method_declaration
| property_declaration
| event_declaration
| indexer_declaration
| operator_declaration
| constructor_declaration
| static_constructor_declaration
| type_declaration
| fixed_size_buffer_declaration // unsafe code support
;
fixed_size_buffer_declaration (§23.8.2) yalnızca güvenli olmayan kodda (§23) kullanılabilir.
Not: finalizer_declaration dışında her türlü class_member_declaration da struct_member_declaration. son not
§16.4'te belirtilen farklar dışında, §15.3 ile §15.12 arasında sağlanan sınıf üyelerinin açıklamaları yapı üyeleri için de geçerlidir.
16.4 Sınıf ve yapı farklılıkları
16.4.1 Genel
Yapılar çeşitli önemli yollarla sınıflardan farklıdır:
- Yapılar değer türleridir (§16.4.2).
- Tüm yapı türleri örtük olarak sınıfından
System.ValueType
devralır (§16.4.3). - Yapı türündeki bir değişkene atama, atanmakta olan değerin bir kopyasını oluşturur (§16.4.4).
- Bir yapının varsayılan değeri, tüm alanları varsayılan değerlerine (§16.4.5) ayarlayarak üretilen değerdir.
- Kutulama ve kutu açma işlemleri, yapı türü ile belirli başvuru türleri (§16.4.6) arasında dönüştürme yapmak için kullanılır.
- Anlamları
this
yapı üyelerinde farklıdır (§16.4.7). - Bir yapı için örnek alanı bildirimlerinin değişken başlatıcıları (§16.4.8) içermesine izin verilmez.
- Bir yapının parametresiz örnek oluşturucu (§16.4.9) bildirmesine izin verilmez.
- Bir yapının sonlandırıcı bildirmesine izin verilmez.
16.4.2 Değer semantiği
Yapılar değer türleridir (§8.3) ve değer semantiğine sahip olduğu söylenir. Sınıflar ise başvuru türleridir (§8.2) ve başvuru semantiğine sahip oldukları söylenir.
Bir yapı türünün değişkeni doğrudan yapının verilerini içerirken, sınıf türündeki bir değişken verileri içeren bir nesneye başvuru içerir. Bir yapı B
türünde A
bir örnek alanı içerdiğinde ve A
bir yapı türündeyse, veya türünden B
oluşturulan bir türe bağımlı B
olması için A
bir derleme zamanı hatasıdır. A struct X
türündeki Y
bir örnek alanı içeriyorsa doğrudan bir yapıya Y
X
bağlıdır. Bu tanım göz önüne alındığında, bir yapının bağımlı olduğu tam yapı kümesi, doğrudan ilişkiye bağlı olan geçişli kapanışıdır.
Örnek:
struct Node { int data; Node next; // error, Node directly depends on itself }
kendi türünde bir örnek alanı içerdiğinden
Node
bir hatadır. Başka bir örnekstruct A { B b; } struct B { C c; } struct C { A a; }
, ve
C
türlerininA
B
her biri birbirine bağlı olduğundan bir hatadır.son örnek
Sınıflarla, iki değişkenin aynı nesneye başvurması ve bu nedenle bir değişkendeki işlemlerin diğer değişken tarafından başvuruda bulunan nesneyi etkilemesi mümkündür. Yapılarla, değişkenlerin her biri kendi veri kopyasına sahiptir (başvuruya göre parametreler hariç) ve birindeki işlemlerin diğerini etkilemesi mümkün değildir. Ayrıca, açıkça null atanabilir (§8.3.12) dışında, yapı türü değerlerinin olması null
mümkün değildir.
Not: Yapı başvuru türünde bir alan içeriyorsa, başvuruda bulunılan nesnenin içeriği diğer işlemler tarafından değiştirilebilir. Ancak alanın kendisi, yani hangi nesneye başvuracağı, farklı bir yapı değerinin mutasyonuyla değiştirilemez. son not
Örnek: Aşağıdakiler göz önünde bulundurulduğunda
struct Point { public int x, y; public Point(int x, int y) { this.x = x; this.y = y; } } class A { static void Main() { Point a = new Point(10, 10); Point b = a; a.x = 100; Console.WriteLine(b.x); } }
çıktısı şeklindedir
10
. öğesinin atamasıa
değerin bir kopyasını oluşturur veb
bu nedenle atamadana.x
etkilenmez.b
BununPoint
yerine sınıf olarak bildirilmiş olsaydı, çıkış nedenia
veb
aynı nesneye başvurması olurdu100
.son örnek
16.4.3 Devralma
Tüm yapı türleri, sırayla sınıfından System.ValueType
devralan sınıfından object
örtük olarak devralır. Yapı bildirimi uygulanan arabirimlerin listesini belirtebilir, ancak yapı bildiriminin bir temel sınıf belirtmesi mümkün değildir.
Yapı türleri asla soyut değildir ve her zaman örtük olarak kapatılır. abstract
Bu nedenle ve sealed
değiştiricilerine bir yapı bildiriminde izin verilmez.
Yapılar için devralma desteklenmediğinden, yapı üyesinin bildirilen erişilebilirliği , private protected
veya protected internal
olamazprotected
.
Yapıdaki işlev üyeleri soyut veya sanal olamaz ve değiştiricinin override
yalnızca öğesinden System.ValueType
devralınan yöntemleri geçersiz kılması için izin verilir.
16.4.4 Atama
Yapı türündeki bir değişkene atama, atanan değerin bir kopyasını oluşturur. Bu, başvuruyu kopyalayan ancak başvuru tarafından tanımlanan nesneyi kopyalayan bir sınıf türünün değişkenine atamadan farklıdır.
Atamaya benzer şekilde, bir yapı değer parametresi olarak geçirildiğinde veya işlev üyesinin sonucu olarak döndürülürse, yapının bir kopyası oluşturulur. Bir yapı, bir başvuru parametresi kullanılarak işlev üyesine başvuru ile geçirilebilir.
Bir yapının özelliği veya dizin oluşturucu bir atamanın hedefi olduğunda, özellik veya dizin oluşturucu erişimiyle ilişkili örnek ifadesi değişken olarak sınıflandırılır. Örnek ifadesi bir değer olarak sınıflandırılırsa, derleme zamanı hatası oluşur. Bu, §12.21.2'de daha ayrıntılı olarak açıklanmıştır.
16.4.5 Varsayılan değerler
§9.3'te açıklandığı gibi, çeşitli değişken türleri oluşturulduklarında varsayılan değerlerine otomatik olarak başlatılır. Sınıf türlerinin ve diğer başvuru türlerinin değişkenleri için bu varsayılan değerdir null
. Ancak, yapılar olamayan null
değer türleri olduğundan, bir yapının varsayılan değeri, tüm değer türü alanlarını varsayılan değerlerine ve tüm başvuru türü alanlarını null
değerine ayarlayarak üretilen değerdir.
Örnek: Yukarıda bildirilen yapıya başvuruda
Point
bulunarak örnekPoint[] a = new Point[100];
ve alanlarını sıfır olarak ayarlayarak dizideki her
Point
bir öğeyix
y
üretilen değere başlatır.son örnek
Bir yapının varsayılan değeri, yapının varsayılan oluşturucusunun (§8.3.3) döndürdiği değere karşılık gelir. Bir sınıftan farklı olarak, bir yapının parametresiz örnek oluşturucu bildirmesine izin verilmez. Bunun yerine, her yapı örtük olarak, tüm alanların varsayılan değerlerine ayarlanmasından elde edilen değeri döndüren parametresiz bir örnek oluşturucuya sahiptir.
Not: Yapılar, varsayılan başlatma durumunu geçerli bir durum olarak değerlendirecek şekilde tasarlanmalıdır. Örnekte
struct KeyValuePair { string key; string value; public KeyValuePair(string key, string value) { if (key == null || value == null) { throw new ArgumentException(); } this.key = key; this.value = value; } }
kullanıcı tanımlı örnek oluşturucu, yalnızca açıkça çağrıldığında değerlere karşı
null
koruma sağlar. BirKeyValuePair
değişkenin varsayılan değer başlatmasına tabi olduğu durumlarda vekey
value
alanları olurnull
ve yapısı bu durumu işlemeye hazır olmalıdır.son not
16.4.6 Kutulama ve kutu açma
Bir sınıf türünün değeri, derleme zamanında başvuruyu başka bir tür object
olarak kabul ederek sınıf tarafından uygulanan bir türe veya arabirim türüne dönüştürülebilir. Benzer şekilde, bir tür object
değeri veya arabirim türündeki bir değer, başvuru değiştirilmeden bir sınıf türüne geri dönüştürülebilir (ancak bu durumda elbette bir çalışma zamanı türü denetimi gereklidir).
Yapılar başvuru türleri olmadığından, bu işlemler yapı türleri için farklı şekilde uygulanır. Yapı türündeki bir değer belirli başvuru türlerine dönüştürüldüğünde (§10.2.9'da tanımlandığı gibi), bir kutulama işlemi gerçekleşir. Benzer şekilde, belirli başvuru türlerinin değeri (§10.3.7'de tanımlandığı gibi) yapı türüne geri dönüştürüldüğünde, bir kutulama kaldırma işlemi gerçekleşir. Sınıf türlerindeki aynı işlemlerden önemli bir fark, kutulama ve kutulamanın yapı değerini kutulanmış örneğin içine veya dışına kopyalamasıdır .
Not: Bu nedenle, bir kutulama veya kutu açma işleminin ardından, kutulanmamışta
struct
yapılan değişiklikler kutulanmışstruct
öğesine yansıtılmaz. son not
Kutulama ve kutu açma hakkında daha fazla bilgi için bkz . §10.2.9 ve §10.3.7.
16.4.7 Bunun anlamı
Bir yapıdaki anlamı this
, §12.8.14'te açıklandığı gibi sınıfın anlamından this
farklıdır. Yapı türü, öğesinden devralınan System.ValueType
bir sanal yöntemi (, veya ToString
gibiEquals
GetHashCode
) geçersiz kıldığında, yapı türünün bir örneği aracılığıyla sanal yöntemin çağrılması, kutulamanın oluşmasına neden olmaz. Yapı bir tür parametresi olarak kullanıldığında ve çağırma türü parametre türünün bir örneği aracılığıyla gerçekleştiğinde bile bu durum geçerlidir.
Örnek:
struct Counter { int value; public override string ToString() { value++; return value.ToString(); } } class Program { static void Test<T>() where T : new() { T x = new T(); Console.WriteLine(x.ToString()); Console.WriteLine(x.ToString()); Console.WriteLine(x.ToString()); } static void Main() => Test<Counter>(); }
Programın çıktısı:
1 2 3
Yan etkileri olması kötü bir stil
ToString
olsa da, örnekte üç çağrısıx.ToString()
için hiçbir kutulama gerçekleşmediğini gösterir.son örnek
Benzer şekilde, üye değer türü içinde uygulandığında kısıtlanmış tür parametresinde bir üyeye erişilirken hiçbir zaman örtük olarak kutulama gerçekleşmez. Örneğin, bir arabirimin ICounter
bir değeri değiştirmek için kullanılabilecek bir yöntemi Increment
içerdiğini varsayalım. Kısıtlama olarak kullanılırsa ICounter
, yönteminin Increment
uygulanması, hiçbir zaman kutulanmış bir kopya değil, üzerinde çağrılan değişkene Increment
bir başvuruyla çağrılır.
Örnek:
interface ICounter { void Increment(); } struct Counter : ICounter { int value; public override string ToString() => value.ToString(); void ICounter.Increment() => value++; } class Program { static void Test<T>() where T : ICounter, new() { T x = new T(); Console.WriteLine(x); x.Increment(); // Modify x Console.WriteLine(x); ((ICounter)x).Increment(); // Modify boxed copy of x Console.WriteLine(x); } static void Main() => Test<Counter>(); }
için ilk çağrı
Increment
, değişkenindekix
değeri değiştirir. Bu, kutulanmış bir kopyasındaki değeri değiştiren ikinci çağrısınaIncrement
x
eşdeğer değildir. Bu nedenle, programın çıkışı şöyledir:0 1 1
son örnek
16.4.8 Alan başlatıcıları
§16.4.5'te açıklandığı gibi, bir yapının varsayılan değeri, 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ğerden oluşur. Bu nedenle bir yapı, örnek alanı bildirimlerinin değişken başlatıcıları içermesine izin vermez. Bu kısıtlama yalnızca örnek alanları için geçerlidir. Bir yapının statik alanlarının değişken başlatıcıları içermesine izin verilir.
Örnek: Aşağıdakiler
struct Point { public int x = 1; // Error, initializer not permitted public int y = 1; // Error, initializer not permitted }
hataya neden oluyor çünkü örnek alanı bildirimleri değişken başlatıcılar içeriyor.
son örnek
16.4.9 Oluşturucular
Bir sınıftan farklı olarak, bir yapının parametresiz örnek oluşturucu bildirmesine izin verilmez. Bunun yerine, her yapı örtük olarak, tüm değer türü alanlarını varsayılan değerlerine ve tüm başvuru türü alanlarının null
(§8.3.3) olarak ayarlanmasından elde edilen değeri döndüren parametresiz bir örnek oluşturucuya sahiptir. Yapı, parametreleri olan örnek oluşturucularını bildirebilir.
Örnek: Aşağıdakiler göz önünde bulundurulduğunda
struct Point { int x, y; public Point(int x, int y) { this.x = x; this.y = y; } } class A { static void Main() { Point p1 = new Point(); Point p2 = new Point(0, 0); } }
deyimleri hem ile
x
oluştururPoint
hemy
de sıfıra başlatılır.son örnek
Yapı örneği oluşturucusunun, argument_list isteğe bağlı olduğu form base(
argument_list)
oluşturucu başlatıcısı eklemesine izin verilmez.
Yapı this
örneği oluşturucusunun parametresi, yapı türünün çıkış parametresine karşılık gelir. Bu nedenle, this
oluşturucunun geri döndüğü her yerde kesinlikle atanmalıdır (§9.4). Benzer şekilde, kesinlikle atanmadan önce oluşturucu gövdesinde (örtük olarak bile) okunamaz.
Yapı örneği oluşturucu bir oluşturucu başlatıcı belirtirse, bu başlatıcı oluşturucunun gövdesinden önce gerçekleşen buna kesin bir atama olarak kabul edilir. Bu nedenle, gövdenin kendisinin başlatma gereksinimleri yoktur.
Örnek: Aşağıdaki örnek oluşturucu uygulamasını göz önünde bulundurun:
struct Point { int x, y; public int X { set { x = value; } } public int Y { set { y = value; } } public Point(int x, int y) { X = x; // error, this is not yet definitely assigned Y = y; // error, this is not yet definitely assigned } }
Oluşturulmakta olan yapının tüm alanları kesinlikle atanana kadar hiçbir örnek işlev üyesi (özellikler
X
veY
için küme erişimcileri dahil) çağrılmaz. Ancak yapı yerine bir sınıf olsaydıPoint
örnek oluşturucu uygulamasına izin verileceğine dikkat edin. Bunun bir özel durumu vardır ve otomatik olarak uygulanan özellikleri içerir (§15.7.4). Kesin atama kuralları (§12.21.2) özellikle bu yapı türünün örnek oluşturucusunun içindeki bir yapı türünün otomatik özelliğine atamayı muaf tutmaktadır: böyle bir atama, otomatik özelliğin gizli yedekleme alanının kesin ataması olarak kabul edilir. Bu nedenle, aşağıdakilere izin verilir:struct Point { public int X { get; set; } public int Y { get; set; } public Point(int x, int y) { X = x; // allowed, definitely assigns backing field Y = y; // allowed, definitely assigns backing field } }
son örnek]
16.4.10 Statik oluşturucular
Yapılar için statik oluşturucular, sınıflarla aynı kuralların çoğunu izler. Bir yapı türü için statik oluşturucunun yürütülmesi, aşağıdaki olayların ilki tarafından bir uygulama etki alanında gerçekleşecek şekilde tetikleniyor:
- Yapı türünün statik bir üyesine başvurulur.
- Yapı türünün açıkça bildirilen oluşturucusunun adı verilir.
Not: Yapı türlerinin varsayılan değerlerinin (§16.4.5) oluşturulması statik oluşturucuyu tetiklemez. (Buna örnek olarak bir dizideki öğelerin ilk değeri gösteriliyor.) son not
16.4.11 Otomatik olarak uygulanan özellikler
Otomatik olarak uygulanan özellikler (§15.7.4), yalnızca özellik erişimcileri tarafından erişilebilen gizli yedekleme alanlarını kullanır.
Not: Bu erişim kısıtlaması, otomatik olarak uygulanan özellikleri içeren yapılardaki oluşturucuların, herhangi bir işlev üyesi çağrılmadan veya oluşturucu döndürülmeden önce tüm alanların kesinlikle atanması gereksinimini karşılamak için genellikle açık bir oluşturucu başlatıcıya ihtiyaç duyduğu anlamına gelir. son not
16.4.12 Güvenli bağlam kısıtlaması
16.4.12.1 Genel
Derleme zamanında her ifade, bu örneğe ve tüm alanlarına güvenli bir şekilde erişilebildiği bir bağlamla ilişkilendirilir. Güvenli bağlam, değerin kaçması için güvenli olan bir ifadeyi kapsayan bir bağlamdır.
Derleme zamanı türü başvuru yapısı olmayan tüm ifadeler, çağıran bağlamı için güvenli bir bağlama sahiptir.
Herhangi bir default
tür için ifade, çağıran bağlamının güvenli bağlamını gösterir.
Derleme zamanı türü bir başvuru yapısı olan varsayılan olmayan ifadeler için aşağıdaki bölümler tarafından tanımlanan bir güvenli bağlamı vardır.
Güvenli bağlam, bir değerin kopyalanabileceği bağlamı kaydeder. güvenli bağlamı olan bir ifadeden E1
güvenli bağlamlı S1
bir ifadeye S2
E2
atama verildiğinde, değerinden S1
daha geniş bir bağlamsa S2
bu bir hatadır.
Başvuru değişkenleri (§9.7.2) için tanımlanan ref-safe-context değerleriyle aynı olan üç farklı güvenli bağlam değeri vardır: bildirim bloğu, işlev-üyesi ve çağıran bağlamı. Bir ifadenin güvenli bağlamı, kullanımını aşağıdaki gibi kısıtlar:
- Bir dönüş bildirimi
return e1
için, güvenli bağlamıe1
arayan bağlamı olmalıdır. - Bir atama
e1 = e2
için güvenli bağlamıe2
, en azından güvenli bağlamı kadar geniş bir bağlame1
olmalıdır.
Bir türün veya out
bağımsız değişkeni varsa ref
(tür olmadığı sürece readonly
alıcı dahil), güvenli bağlamlı S1
bir ref struct
yöntem çağrısı için, bağımsız değişkenin (alıcı dahil) daha S1
dar bir güvenli bağlamı olamaz.
16.4.12.2 Parametre güvenli bağlamı
Bir örnek yönteminin parametresi de dahil olmak üzere this
bir başvuru yapısı türünün parametresi, çağıran bağlamı için güvenli bir bağlama sahiptir.
16.4.12.3 Yerel değişken güvenli bağlamı
Bir başvuru yapısı türünün yerel değişkeni aşağıdaki gibi güvenli bir bağlama sahiptir:
- Değişken bir
foreach
döngünün yineleme değişkeniyse değişkenin güvenli bağlamı, döngünün ifadesinin güvenli bağlamıforeach
ile aynıdır. - Aksi takdirde değişkenin bildiriminde başlatıcı varsa değişkenin güvenli bağlamı, bu başlatıcının güvenli bağlamı ile aynıdır.
- Aksi takdirde değişken bildirim noktasında başlatılmaz ve çağıran bağlamı için güvenli bir bağlama sahiptir.
16.4.12.4 Alan güvenli bağlamı
türü bir başvuru yapısı türü olan F
bir alana e.F
yapılan başvuru, güvenli bağlamı ile aynı olan bir güvenli bağlama e
sahiptir.
16.4.12.5 İşleçleri
Kullanıcı tanımlı işlecin uygulaması, yöntem çağırma (§16.4.12.6) olarak değerlendirilir.
veya c ? e1 : e2
gibi e1 + e2
bir değer veren bir işleç için, sonucun güvenli bağlamı işlecin işlenenlerinin güvenli bağlamları arasındaki en dar bağlamdır. Sonuç olarak, gibi +e
bir değer veren birli işleç için sonucun güvenli bağlamı işlenenin güvenli bağlamıdır.
Not: Koşullu işlecin ilk işleneni bir
bool
'dir, bu nedenle güvenli bağlamı çağıran bağlamıdır. Elde edilen güvenli bağlamın ikinci ve üçüncü işlenenin en dar güvenli bağlamı olduğunu izler. son not
16.4.12.6 Yöntem ve özellik çağırma
Yöntem çağrısından e1.M(e2, ...)
veya özellik çağırmasından e.P
kaynaklanan bir değer, aşağıdaki bağlamların en küçükünün güvenli bağlamını içerir:
- çağıran bağlamı.
- Tüm bağımsız değişken ifadelerinin (alıcı dahil) güvenli bağlamı.
Bir özellik çağırması ( get
veya set
) yukarıdaki kurallar tarafından temel alınan yöntemin bir yöntem çağrısı olarak değerlendirilir.
16.4.12.7 stackalloc
Stackalloc ifadesinin sonucu, işlev-üyesinin güvenli bağlamını gösterir.
16.4.12.8 Oluşturucu çağrıları
Oluşturucu new
çağıran bir ifade, oluşturmakta olan türü döndürmek için kabul edilen bir yöntem çağrısı ile aynı kurallara uyar.
Ayrıca güvenli bağlam, herhangi bir başlatıcı varsa özyinelemeli olarak tüm nesne başlatıcı ifadelerinin tüm bağımsız değişkenlerin ve işlenenlerin güvenli bağlamlarının en küçüktür.
Not: Bu kurallar aşağıdaki formun oluşturucusunun olmamasını gerektirir
Span<T>
:public Span<T>(ref T p)
Böyle bir oluşturucu, alan olarak kullanılan örnekleri
Span<T>
birref
alandan ayırt edilemez hale getirir. Bu belgede açıklanan güvenlik kuralları, alanların C# veya .NET'te geçerli bir yapı olmamasına bağlıdırref
. son not
ECMA C# draft specification