Aracılığıyla paylaş


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 structverilerini 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 , doubleve boolgibi intbasit 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.

readonlydışı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.Objectiç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üne object System.ValueTypedö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 bir ref struct örnek yöntemi, bu ref 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, A ref struct örnek yöntemlerini bildirmez async veya yield 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.ValueTypedevralı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 Boluşturulan bir türe bağımlı B olması için A bir derleme zamanı hatasıdır. A struct Xtü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 örnek

struct A { B b; }
struct B { C c; }
struct C { A a; }

, ve C türlerinin ABher 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ı nullmü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 ve b bu nedenle atamadan a.xetkilenmez.b Bunun Point yerine sınıf olarak bildirilmiş olsaydı, çıkış nedeni a ve b aynı nesneye başvurması olurdu100.

son örnek

16.4.3 Devralma

Tüm yapı türleri, sırayla sınıfından System.ValueTypedevralan 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 protectedveya protected internalolamazprotected.

Yapıdaki işlev üyeleri soyut veya sanal olamaz ve değiştiricinin override yalnızca öğesinden System.ValueTypedevralı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 nulldeğ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ı nulldeğerine ayarlayarak üretilen değerdir.

Örnek: Yukarıda bildirilen yapıya başvuruda Point bulunarak örnek

Point[] a = new Point[100];

ve alanlarını sıfır olarak ayarlayarak dizideki her Point bir öğeyi x 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. Bir KeyValuePair değişkenin varsayılan değer başlatmasına tabi olduğu durumlarda ve key value alanları olur nullve 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 ToStringgibiEqualsGetHashCode) 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 Incrementiç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şkenindeki xdeğeri değiştirir. Bu, kutulanmış bir kopyasındaki değeri değiştiren ikinci çağrısına Incrementxeş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ı nullolarak 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şturur Point hem y 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 ve Yiç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ı S1bir ifadeye S2E2 atama verildiğinde, değerinden S1daha 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 e1iç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ğlam e1olmalıdır.

Bir türün veya out bağımsız değişkeni varsa ref (tür olmadığı sürece readonlyalıcı dahil), güvenli bağlamlı S1bir ref struct yöntem çağrısı için, bağımsız değişkenin (alıcı dahil) daha S1dar 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.Fyapılan başvuru, güvenli bağlamı ile aynı olan bir güvenli bağlama esahiptir.

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 : e2gibi 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 +ebir 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> bir ref 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ır ref . son not