Aracılığıyla paylaş


9 Değişken

9.1 Genel

Değişkenler depolama konumlarını temsil eder. Her değişkenin, değişkende hangi değerlerin depolanabileceğini belirleyen bir türü vardır. C# tür açısından güvenli bir dildir ve C# derleyicisi, değişkenlerde depolanan değerlerin her zaman uygun türde olduğunu garanti eder. Bir değişkenin değeri atama yoluyla veya ve ++ işleçlerinin -- kullanımıyla değiştirilebilir.

Değer elde edilebilmesi için bir değişken kesinlikle atanmalıdır (§9.4).

Aşağıdaki alt öğelerde açıklandığı gibi, değişkenler başlangıçta atanır veya başlangıçta atanmamış olur. Başlangıçta atanan bir değişkenin iyi tanımlanmış bir başlangıç değeri vardır ve her zaman kesinlikle atanmış olarak kabul edilir. Başlangıçta atanmamış bir değişkenin başlangıç değeri yoktur. Başlangıçta atanmamış bir değişkenin belirli bir konumda kesinlikle atanmış olarak kabul edilmesi için, bu konuma giden tüm olası yürütme yollarında değişkene bir atama gerçekleşir.

9.2 Değişken kategorileri

9.2.1 Genel

C# sekiz değişken kategorisini tanımlar: statik değişkenler, örnek değişkenleri, dizi öğeleri, değer parametreleri, giriş parametreleri, başvuru parametreleri, çıkış parametreleri ve yerel değişkenler. İzleyen alt bölümler bu kategorilerin her birini açıklar.

Örnek: Aşağıdaki kodda

class A
{
    public static int x;
    int y;

    void F(int[] v, int a, ref int b, out int c, in int d)
    {
        int i = 1;
        c = a + b++ + d;
    }
}

x statik değişkendir, y örnek değişkenidir, v[0] dizi öğesidir, a değer parametresidir, b başvuru parametresidir, c çıkış parametresidir, d giriş parametresidir ve i yerel bir değişkendir. son örnek

9.2.2 Statik değişkenler

Değiştirici ile static bildirilen bir alan statik değişkendir. Statik değişken, oluşturucunun static (§15.12) içeren türü için yürütülmesinden önce ortaya çıkar ve ilişkili uygulama etki alanı sona erdiğinde yok olur.

Statik değişkenin ilk değeri, değişkenin türünün varsayılan değeridir (§9,3).

Kesin atama denetimi amacıyla, statik değişken başlangıçta atanmış olarak kabul edilir.

9.2.3 Örnek değişkenleri

9.2.3.1 Genel

Değiştirici olmadan static bildirilen bir alan bir örnek değişkenidir.

Sınıflarda 9.2.3.2 Örnek değişkenleri

Bir sınıfın örnek değişkeni, söz konusu sınıfın yeni bir örneği oluşturulduğunda ortaya çıkar ve söz konusu örneğe başvuru olmadığında ve örneğin sonlandırıcısı (varsa) yürütülürse yok olur.

Bir sınıfın örnek değişkeninin ilk değeri, değişkenin türünün varsayılan değeridir (§9,3).

Kesin atama denetimi amacıyla, bir sınıfın örnek değişkeni başlangıçta atanmış olarak kabul edilir.

Yapılardaki 9.2.3.3 Örnek değişkenleri

Bir yapının örnek değişkeni, ait olduğu yapı değişkeniyle tam olarak aynı yaşam süresine sahiptir. Başka bir deyişle, bir yapı türünün değişkeni ortaya çıktığında veya var olmaktan çıktığında, yapının örnek değişkenleri de öyle olur.

Bir yapının örnek değişkeninin ilk atama durumu, içeren struct değişkeninkiyle aynıdır. Başka bir deyişle, bir yapı değişkeni başlangıçta atanmış olarak kabul edildiğinde, örnek değişkenleri de öyledir ve bir yapı değişkeni başlangıçta atanmamış olarak kabul edildiğinde, örnek değişkenleri de benzer şekilde atanmamış olur.

9.2.4 Dizi öğeleri

Dizi örneği oluşturulduğunda dizinin öğeleri ortaya çıkar ve bu dizi örneğine başvuru olmadığında yok olur.

Bir dizinin öğelerinin her birinin başlangıç değeri, dizi öğelerinin türünün varsayılan değeridir (§9,3).

Kesin atama denetimi amacıyla, bir dizi öğesi başlangıçta atanmış olarak kabul edilir.

9.2.5 Değer parametreleri

Bir değer parametresi, parametrenin ait olduğu işlev üyesinin (yöntem, örnek oluşturucu, erişimci veya işleç) veya anonim işlevin çağrılması üzerine ortaya çıkar ve çağrıda verilen bağımsız değişkenin değeriyle başlatılır. İşlev gövdesinin yürütülmesi tamamlandığında bir değer parametresi normalde sona erer. Ancak, değer parametresi anonim bir işlev (§12.19.6.2) tarafından yakalanırsa, en azından söz konusu anonim işlevden oluşturulan temsilci veya ifade ağacı çöp toplama için uygun olana kadar süresi uzatılır.

Kesin atama denetimi amacıyla, bir değer parametresi başlangıçta atanmış olarak kabul edilir.

Değer parametreleri §15.6.2.2'de daha ayrıntılı olarak ele alınıyor.

9.2.6 Başvuru parametreleri

Başvuru parametresi, işlev üyesinin, temsilcinin, anonim işlevin veya yerel işlevin çağrılması üzerine ortaya çıkan bir başvuru değişkenidir (§9.7) ve başvuranı bu çağrıda bağımsız değişken olarak verilen değişkene başlatılır. İşlev gövdesinin yürütülmesi tamamlandığında bir başvuru parametresi yok olur. Değer parametrelerinin aksine bir başvuru parametresi yakalanmaz (§9.7.2.9).

Aşağıdaki kesin atama kuralları başvuru parametreleri için geçerlidir.

Not: Çıkış parametrelerinin kuralları farklıdır ve (§9.2.7) içinde açıklanmıştır. son not

  • Bir değişken, bir işlev üyesi veya temsilci çağrısında başvuru parametresi olarak geçirilmeden önce kesinlikle atanmalıdır (§9.4).
  • bir işlev üyesi veya anonim işlev içinde, başlangıçta bir başvuru parametresi atanmış olarak kabul edilir.

Başvuru parametreleri §15.6.2.3.3'te daha ayrıntılı olarak ele alınıyor.

9.2.7 Çıkış parametreleri

Çıkış parametresi, işlev üyesinin, temsilcinin, anonim işlevin veya yerel işlevin çağrılması üzerine ortaya çıkan bir başvuru değişkenidir (§9.7) ve başvuranı bu çağrıda bağımsız değişken olarak verilen değişkene başlatılır. İşlev gövdesinin yürütülmesi tamamlandığında bir çıkış parametresi yok olur. Değer parametrelerinin aksine çıkış parametresi yakalanmaz (§9.7.2.9).

Aşağıdaki kesin atama kuralları çıkış parametreleri için geçerlidir.

Not: Başvuru parametrelerinin kuralları farklıdır ve (§9.2.6) içinde açıklanmıştır. son not

  • Bir değişken, bir işlev üyesinde veya temsilci çağırmasında çıkış parametresi olarak geçirilmeden önce kesinlikle atanmamalıdır.
  • Bir işlev üyesi veya temsilci çağrısının normal tamamlanmasının ardından, çıkış parametresi olarak geçirilen her değişken bu yürütme yolunda atanmış olarak kabul edilir.
  • İşlev üyesi veya anonim işlevde, çıkış parametresi başlangıçta atanmamış olarak kabul edilir.
  • İşlev üyesi, anonim işlev veya yerel işlevin her çıkış parametresi, işlev üyesi, anonim işlev veya yerel işlev normal şekilde döndürmeden önce kesinlikle atanmalıdır (§9.4).

Çıkış parametreleri §15.6.2.3.4'te daha ayrıntılı olarak ele alınmaktadır.

9.2.8 Giriş parametreleri

Giriş parametresi, işlev üyesi, temsilci, anonim işlev veya yerel işlevin çağrılması üzerine ortaya çıkan bir başvuru değişkenidir (§9.7) ve bu çağrıda bağımsız değişken olarak verilen variable_reference için başvuran başlatılır. İşlev gövdesinin yürütülmesi tamamlandığında bir giriş parametresi yok olur. Değer parametrelerinin aksine bir giriş parametresi yakalanmaz (§9.7.2.9).

Aşağıdaki kesin atama kuralları giriş parametreleri için geçerlidir.

  • Bir değişken, işlev üyesi veya temsilci çağrısında giriş parametresi olarak geçirilmeden önce kesinlikle atanmalıdır (§9.4).
  • bir işlev üyesi, anonim işlev veya yerel işlev içinde giriş parametresi başlangıçta atanmış olarak kabul edilir.

Giriş parametreleri §15.6.2.3.2'de daha ayrıntılı olarak ele alınıyor.

9.2.9 Yerel değişkenler

9.2.9.1 Genel

Yerel değişken bir try_statement local_variable_declaration, declaration_expression, foreach_statement veya specific_catch_clause tarafından bildirilir. Yerel değişken belirli desentürleri (§11) tarafından da bildirilebilir. bir foreach_statement için yerel değişken bir yineleme değişkenidir (§13.9.5). bir specific_catch_clause için yerel değişken bir özel durum değişkenidir (§13.11). bir foreach_statement veya specific_catch_clause tarafından bildirilen bir yerel değişken başlangıçta atanmış olarak kabul edilir.

Local_variable_declaration bir blokta, for_statement, switch_block veya using_statement oluşabilir. declaration_expression bir argument_value ve bir yapı kaldırma atamasının (§12.21.2) hedefi olan bir tuple_elementoutgerçekleşebilir .

Yerel değişkenin ömrü, program yürütmesinin depolama alanı için ayrılacağı garanti edilen bölümüdür. Bu yaşam süresi, en azından bu kapsamın yürütülmesi bir şekilde sona erene kadar girişten ilişkilendirildiği kapsama kadar uzanır. (Kapalı bir blok girilmesi, yöntemin çağrılması veya yineleyici bloğundan bir değer verilmesi geçerli kapsamın yürütülmesini askıya alır, ancak sona ermez.) Yerel değişken anonim bir işlev (§12.19.6.2) tarafından yakalanırsa, en azından anonim işlevden oluşturulan temsilci veya ifade ağacının yanı sıra yakalanan değişkene başvurmaya gelen diğer nesneler çöp toplama için uygun olana kadar ömrü uzatılır. Üst kapsam yinelemeli veya yinelemeli olarak girilirse, her seferinde yeni bir yerel değişken örneği oluşturulur ve varsa başlatıcısı her seferinde değerlendirilir.

Not: Kapsamı her girildiğinde yerel değişken örneği oluşturulur. Bu davranış, anonim yöntemler içeren kullanıcı kodu tarafından görülebilir. son not

Not: bir foreach_statement tarafındanbildirilen bir yineleme değişkeninin (§13.9.5) ömrü, bu deyimin tek bir yinelemesidir. Her yineleme yeni bir değişken oluşturur. son not

Not: Yerel değişkenin gerçek ömrü uygulamaya bağlıdır. Örneğin, bir derleyici bloktaki yerel değişkenin yalnızca bu bloğun küçük bir bölümü için kullanıldığını statik olarak belirleyebilir. Bir derleyici bu çözümlemeyi kullanarak değişkenin depolama alanının, içeren bloğundan daha kısa bir süreye sahip olmasına neden olan bir kod oluşturabilir.

Yerel başvuru değişkeni tarafından başvuruda bulunılan depolama, bu yerel başvuru değişkeninin (§7.9) ömründen bağımsız olarak geri kazanılır.

son not

bir local_variable_declaration veya declaration_expression tarafından sunulan yerel değişken otomatik olarak başlatılmaz ve bu nedenle varsayılan değeri yoktur. Böyle bir yerel değişken başlangıçta atanmamış olarak kabul edilir.

Not: Başlatıcı içeren bir local_variable_declaration başlangıçta hala atanmamış durumdadır. Bildirimin yürütülmesi, değişkene yapılan bir atama gibi davranır (§9.4.4.5). Başlatıcısı yürütülmeden önce bir değişken kullanma; Örneğin, başlatıcı ifadesinin içinde veya başlatıcıyı atlayan bir goto_statement kullanarak; derleme zamanı hatasıdır:

goto L;

int x = 1; // never executed

L: x += 1; // error: x not definitely assigned

Yerel değişken kapsamında, bu yerel değişkene bildirimciden önce gelen metinsel bir konumda başvurmak bir derleme zamanı hatasıdır.

son not

9.2.9.2 Atıklar

Atma, adı olmayan yerel bir değişkendir. Atma, tanımlayıcısı olan bir bildirim ifadesi (§12.17) tarafından tanıtılır ve örtük olarak (_ veya ) veya _açıkça () yazılırvar _.T _

Not: _ birçok bildirim biçiminde geçerli bir tanımlayıcıdır. son not

Bir atma işleminin adı olmadığından, temsil ettiği değişkenin tek başvurusu onu tanıtır ifadesidir.

Not: Ancak bir atma, ilgili çıkış parametresinin ilişkili depolama konumunu belirtmesine izin veren bir çıkış bağımsız değişkeni olarak geçirilebilir. son not

Atma işlemi başlangıçta atanmadığından değerine erişmek her zaman bir hatadır.

Örnek:

_ = "Hello".Length;
(int, int, int) M(out int i1, out int i2, out int i3) { ... }
(int _, var _, _) = M(out int _, out var _, out _);

Örnekte kapsamda adın _ bildiriminin olmadığı varsayılır.

ataması _ , bir ifadenin sonucunu yoksaymak için basit bir desen gösterir. çağrısı M , tanımlama listelerinde ve çıkış parametreleri olarak kullanılabilen farklı atma biçimlerini gösterir.

son örnek

9.3 Varsayılan değerler

Aşağıdaki değişken kategorileri, varsayılan değerlerine otomatik olarak başlatılır:

  • Statik değişkenler.
  • Sınıf örneklerinin örnek değişkenleri.
  • Dizi öğeleri.

Bir değişkenin varsayılan değeri değişkenin türüne bağlıdır ve aşağıdaki gibi belirlenir:

Not: Varsayılan değerlere başlatma işlemi genellikle bellek yöneticisinin veya çöp toplayıcının kullanıma ayrılmadan önce belleği all-bits-zero olarak başlatmasını sağlayarak yapılır. Bu nedenle, null başvuruyu temsil etmek için all-bits-zero kullanmak uygundur. son not

9.4 Kesin atama

9.4.1 Genel

İşlev üyesinin veya anonim bir işlevin yürütülebilir kodundaki belirli bir konumda, bir derleyici belirli bir statik akış analizi tarafından (§9.4.4) değişkenin otomatik olarak başlatıldığını veya en az bir atamanın hedefi olduğunu kanıtlayabilirse değişkenin kesinlikle atandığı söylenir.

Not: Resmi olmayan bir şekilde, kesin atama kuralları şunlardır:

  • Başlangıçta atanan bir değişken (§9.4.2) her zaman kesinlikle atanmış olarak kabul edilir.
  • Başlangıçta atanmamış bir değişken (§9.4.3), söz konusu konuma giden tüm olası yürütme yolları aşağıdakilerden en az birini içeriyorsa, belirli bir konumda kesinlikle atanmış olarak kabul edilir:
    • Değişkenin sol işlenen olduğu basit bir atama (§12.21.2).
    • Değişkeni çıkış parametresi olarak geçiren bir çağırma ifadesi (§12.8.10) veya nesne oluşturma ifadesi (§12.8.17.2).
    • Yerel değişken için, değişken başlatıcısı içeren değişkenin (§13.6.2) yerel değişken bildirimi.

Yukarıdaki resmi olmayan kuralları temel alan resmi belirtim §9.4.2, §9.4.3 ve §9.4.4'te açıklanmıştır.

son not

bir struct_type değişkeninin örnek değişkenlerinin kesin atama durumları hem ayrı ayrı hem de toplu olarak izlenir. §9.4.2, §9.4.3 ve §9.4.4'te açıklanan kurallara ek olarak, aşağıdaki kurallar struct_type değişkenleri ve bunların örnek değişkenleri için geçerlidir:

  • Bir örnek değişkeni, içeren struct_type değişkeni kesinlikle atanmış olarak kabul edilirse kesinlikle atanmış olarak kabul edilir.
  • Struct_type değişkenlerinin her biri kesinlikle atanmış olarak kabul edilirse, bir struct_type değişkeni kesinlikle atanmış olarak kabul edilir.

Kesin atama aşağıdaki bağlamlarda bir gereksinimdir:

  • Bir değişken, değerinin elde edildiği her konuma kesinlikle atanmalıdır.

    Not: Bu, tanımsız değerlerin hiçbir zaman oluşmamasını sağlar. son not

    Bir ifadedeki değişkenin oluşumu, değişkenin değerini almak için kabul edilir, ancak

    • değişkeni, basit bir atamanın sol işlenenidir,
    • değişkeni bir çıkış parametresi olarak geçirilir veya
    • değişkeni bir struct_type değişkenidir ve üye erişiminin sol işleneni olarak gerçekleşir.
  • Bir değişken, başvuru parametresi olarak geçirildiği her konuma kesinlikle atanmalıdır.

    Not: Bu, çağrılan işlev üyesinin başlangıçta atanan başvuru parametresini dikkate alabilmesini sağlar. son not

  • Bir değişken, giriş parametresi olarak geçirildiği her konuma kesinlikle atanmalıdır.

    Not: Bu, çağrılan işlev üyesinin başlangıçta atanan giriş parametresini dikkate alabilmesini sağlar. son not

  • İşlev üyesinin tüm çıkış parametreleri, işlev üyesinin döndürdüğü her konumda (bir dönüş deyimi aracılığıyla veya işlev üyesi gövdesinin sonuna ulaşan yürütme yoluyla) kesinlikle atanmalıdır.

    Not: Bu, işlev üyelerinin çıkış parametrelerinde tanımsız değerler döndürmemesini sağlar, böylece derleyicinin değişkeni değişken atamasına eşdeğer bir çıkış parametresi olarak alan bir işlev üyesi çağırmasını dikkate almasını sağlar. son not

  • this bir struct_type örneği oluşturucusunun değişkeni, söz konusu örnek oluşturucunun döndürdüğü her konuma kesinlikle atanmalıdır.

9.4.2 Başlangıçta atanan değişkenler

Aşağıdaki değişken kategorileri başlangıçta atanmış olarak sınıflandırılır:

  • Statik değişkenler.
  • Sınıf örneklerinin örnek değişkenleri.
  • Başlangıçta atanan yapı değişkenlerinin örnek değişkenleri.
  • Dizi öğeleri.
  • Değer parametreleri.
  • Başvuru parametreleri.
  • Giriş parametreleri.
  • Yan tümcesinde veya catch deyiminde foreach bildirilen değişkenler.

9.4.3 Başlangıçta atanmamış değişkenler

Aşağıdaki değişken kategorileri başlangıçta atanmamış olarak sınıflandırılır:

  • Başlangıçta atanmamış yapı değişkenlerinin örnek değişkenleri.
  • Oluşturucu başlatıcısı olmayan yapı örneği oluşturucularının değişkeni de dahil olmak üzere this çıkış parametreleri.
  • Yan catch tümcesinde veya foreach deyiminde bildirilenler dışında yerel değişkenler.

9.4.4 Kesin atamayı belirlemek için kesin kurallar

9.4.4.1 Genel

Kullanılan her değişkenin kesinlikle atandığını belirlemek için, derleyici bu alt bölümde açıklanana eşdeğer bir işlem kullanacaktır.

İşlev üyesinin gövdesi başlangıçta atanmamış bir veya daha fazla değişken bildirebilir. başlangıçta atanmamış her değişken viçin bir derleyici, işlev üyesinde aşağıdaki noktaların her birinde v için kesin atama durumu belirler:

  • Her deyimin başında
  • Her deyimin bitiş noktasında (§13.2)
  • Denetimi başka bir deyime veya deyimin bitiş noktasına aktaran her yay üzerinde
  • Her ifadenin başında
  • Her ifadenin sonunda

v'nin kesin atama durumu aşağıdakilerden biri olabilir:

  • Kesinlikle atandı. Bu, bu noktaya tüm olası denetim akışlarında v'ye bir değer atandığını gösterir.
  • Kesinlikle atanmadı. türündeki boolbir ifadenin sonundaki bir değişkenin durumu için, kesinlikle atanmamış bir değişkenin durumu aşağıdaki alt durumlardan birine düşebilir (ancak gerekli değildir):
    • True ifadeden sonra kesinlikle atanmıştır. Bu durum, Boole ifadesi true olarak değerlendirilirse v'nin kesinlikle atandığını, ancak Boole ifadesinin false olarak değerlendirildiğinde atanması gerekmediğini gösterir.
    • False ifadeden sonra kesinlikle atanmış. Bu durum, Boole ifadesi false olarak değerlendirilirse v'nin kesinlikle atandığını, ancak Boole ifadesinin true olarak değerlendirildiğinde atanması gerekmediğini gösterir.

Aşağıdaki kurallar, bir değişken v'nin durumunun her konumda nasıl belirlendiğini yönetir.

9.4.4.2 Deyimler için genel kurallar

  • v , işlev üyesi gövdesinin başında kesinlikle atanmamış.
  • Diğer herhangi bir deyimin başındaki v'nin kesin atama durumu, bu deyimin başlangıcını hedefleyen tüm denetim akışı aktarımlarında v'nin kesin atama durumu denetlenerek belirlenir. V bu tür tüm denetim akışı aktarımlarında kesinlikle atanmışsa (ve yalnızca bu durumda), v kesinlikle deyiminin başında atanır. Olası denetim akışı aktarımları kümesi, denetim deyimi ulaşılabilirliği (§13.2) ile aynı şekilde belirlenir.
  • , , , , , , blockcheckeduncheckedifwhiledoveya for deyiminin bitiş noktasındaki v'nin foreachlock, bu deyimin bitiş noktasını hedefleyen tüm denetim akışı aktarımlarında v'nin using kesin atama durumu denetlenerek belirlenir. switch V bu tür tüm denetim akışı aktarımlarında kesinlikle atanmışsa, v kesinlikle deyiminin bitiş noktasına atanır. Aksi takdirde, v deyiminin bitiş noktasında kesinlikle atanmamış olur. Olası denetim akışı aktarımları kümesi, denetim deyimi ulaşılabilirliği (§13.2) ile aynı şekilde belirlenir.

Not: Ulaşılamayan bir deyimin denetim yolları olmadığından, v kesinlikle erişilemeyen herhangi bir deyimin başında atanır. son not

9.4.4.3 Deyimleri, işaretli ve işaretsiz deyimleri engelleme

Bloktaki deyim listesinin ilk deyimine (veya deyim listesi boşsa bloğun bitiş noktasına) denetim aktarımında v'nin kesin atama durumu, blok, veya checked deyiminden önceki v'nin unchecked kesin atama deyimiyle aynıdır.

9.4.4.4 İfade deyimleri

İfade ifade ifadelerinden oluşan bir ifade deyimi stmt için:

  • v, ifadenin başında stmt'nin başındakiyle aynı kesin atama durumuna sahiptir.
  • Eğer v kesinlikle expr sonunda atanmışsa, kesinlikle stmt'nin bitiş noktasında atanır; aksi takdirde, kesinlikle stmt'nin bitiş noktasında atanmamış olur.

9.4.4.5 Bildirim bildirimleri

  • stmt başlatıcıları olmayan bir bildirim deyimiyse, v, stmt'nin bitiş noktasında stmt'ninbaşındakiyle aynı kesin atama durumuna sahiptir.
  • stmt başlatıcıları olan bir bildirim deyimiyse, v için kesin atama durumu, stmt'nin bir deyim listesi olduğu ve başlatıcısı olan her bildirim için bir atama deyimi olduğu (bildirim sırasına göre) olarak belirlenir.

9.4.4.6 If deyimleri

Formun deyim stmt değeri için:

if ( «expr» ) «then_stmt» else «else_stmt»
  • v, ifadenin başında stmt'nin başındakiyle aynı kesin atama durumuna sahiptir.
  • İfadenin sonunda kesinlikle v atanmışsa, denetim akışı aktarımında kesinlikle then_stmt ve else_stmt ya dabaşka yan tümcesi yoksa stmt'ninbitiş noktasına atanır.
  • İfadenin sonunda v "kesinlikle true ifadeden sonra atanmış" durumuna sahipse, denetim akışı aktarımında kesinlikle then_stmt atanır ve denetim akışı aktarımında kesinlikle else_stmt veya başka yan tümcesi yoksa stmt'nin bitiş noktasına atanmamıştır.
  • İfadenin sonunda v "false ifadeden sonra kesinlikle atanmış" durumuna sahipse, denetim akışı aktarımında kesinlikle else_stmt atanır ve then_stmt denetim akışı aktarımında kesinlikle atanmamıştır. Stmt'nin bitiş noktasında ve yalnızca then_stmt bitiş noktasında kesinlikle atanmışsa kesinlikle atanır.
  • Aksi takdirde v, denetim akışı aktarımında then_stmt veya else_stmt ya da başka yan tümcesi yoksa stmt'nin bitiş noktasına kesinlikle atanmadığı kabul edilir.

9.4.4.7 Switch deyimleri

Denetimli ifadeli switch bir stmt deyimi için:

İfadenin başındaki v'nin kesin atama durumu, stmt'nin başındaki v durumuyla aynıdır.

Bir servis talebinin guard yan tümcesinin başındaki v'nin kesin atama durumu şudur:

  • v, switch_label bildirilen bir desen değişkeniyse: "kesinlikle atanmış".
  • Bu koruma yan tümcesini (§13.8.3) içeren anahtar etiketine ulaşılamıyorsa: "kesinlikle atanmış".
  • Aksi takdirde, v durumu ifadeden sonraki v durumuyla aynıdır.

Örnek: İkinci kural, ulaşılamayan kodda atanmamış bir değişkene erişilirse derleyicinin hata verme gereksinimini ortadan kaldırır. Ulaşılamayan anahtar etiketinde bcase 2 when b"kesinlikle atanmıştır".

bool b;
switch (1) 
{
    case 2 when b: // b is definitely assigned here.
    break;
}

son örnek

Erişilebilir bir anahtar bloğu deyimi listesine denetim akışı aktarımında v'nin kesin atama durumu şudur:

  • Denetim aktarımı 'goto case' veya 'goto default' deyiminden kaynaklanıyorsa, v'nin durumu bu 'goto' deyiminin başındaki durumla aynıdır.
  • Denetim aktarımı anahtarın default etiketinden kaynaklanıyorsa, v'nindurumu ifadeden sonraki v durumuyla aynıdır.
  • Denetim aktarımı ulaşılamayan bir anahtar etiketinden kaynaklanıyorsa v'nin durumu "kesinlikle atanmış" olur.
  • Denetim aktarımı bir guard yan tümcesine sahip erişilebilir bir anahtar etiketinden kaynaklanıyorsa, v'nin durumu, guard yan tümcesi sonrasındaki v durumuyla aynıdır.
  • Denetim aktarımı bir guard yan tümcesi olmadan ulaşılabilir bir anahtar etiketinden kaynaklanıyorsa, v'nin durumu
    • v, switch_label bildirilen bir desen değişkeniyse: "kesinlikle atanmış".
    • Aksi takdirde, v'nindurumu ifadeden sonra v'nin durumuyla aynıdır.

Bu kuralların bir sonucu, switch_label bildirilen bir desen değişkeninin, bölümünde erişilebilen tek anahtar etiketi değilse switch bölümünün deyimlerinde "kesinlikle atanmaması"dır.

Örnek:

public static double ComputeArea(object shape)
{
    switch (shape)
    {
        case Square s when s.Side == 0:
        case Circle c when c.Radius == 0:
        case Triangle t when t.Base == 0 || t.Height == 0:
        case Rectangle r when r.Length == 0 || r.Height == 0:
            // none of s, c, t, or r is definitely assigned
            return 0;
        case Square s:
            // s is definitely assigned
            return s.Side * s.Side;
        case Circle c:
            // c is definitely assigned
            return c.Radius * c.Radius * Math.PI;
           …
    }
}

son örnek

9.4.4.8 While deyimleri

Formun deyim stmt değeri için:

while ( «expr» ) «while_body»
  • v, ifadenin başında stmt'nin başındakiyle aynı kesin atama durumuna sahiptir.
  • v kesinlikle ifadenin sonunda atanmışsa, denetim akışı aktarımında kesinlikle while_body ve stmt'nin bitiş noktasına atanır.
  • İfadenin sonunda v "kesinlikle true ifadeden sonra atanmış" durumuna sahipse, denetim akışı aktarımında kesinlikle while_body atanır, ancak kesinlikle stmt'nin bitiş noktasında atanmamıştır.
  • İfadenin sonunda v "kesinlikle yanlış ifadeden sonra atanmış" durumuna sahipse, denetim akışı aktarımında kesinlikle stmt'nin bitiş noktasına atanır, ancak while_body denetim akışı aktarımında kesinlikle atanmamıştır.

9.4.4.9 Do deyimleri

Formun deyim stmt değeri için:

do «do_body» while ( «expr» ) ;
  • v, denetim akışı aktarımında stmt'nin başından do_body stmt'ninbaşındakiyle aynı kesin atama durumuna sahiptir.
  • v, ifadenin başında do_body bitiş noktasındakiyle aynı kesin atama durumuna sahiptir.
  • İfadenin sonunda kesinlikle v atanmışsa, denetim akışı aktarımında kesinlikle stmt'nin bitiş noktasına atanır.
  • İfadenin sonunda v "false ifadeden sonra kesinlikle atanmış" durumuna sahipse, denetim akışı aktarımında kesinlikle stmt'nin bitiş noktasına atanır, ancak denetim akışı aktarımında kesinlikle do_body atanmamış olur.

9.4.4.10 For deyimleri

Formun deyimi için:

for ( «for_initializer» ; «for_condition» ; «for_iterator» )
    «embedded_statement»

deyimi yazılmış gibi kesin atama denetimi yapılır:

{
    «for_initializer» ;
    while ( «for_condition» )
    {
        «embedded_statement» ;
        LLoop: «for_iterator» ;
    }
}

etiketini hedefleyen continue deyimlere çevrilen for deyimini gotohedefleyen deyimlerle.LLoop for_condition deyiminden atlanırsa, yukarıdaki genişletmede for_conditionforkesin atama değerlendirmesi devam eder.

9.4.4.11 Break, continue ve goto deyimleri

, veya deyiminin break kesin atama durumu, continuedeyiminin başındaki v'nin goto kesin atama durumuyla aynıdır.

9.4.4.12 Throw deyimleri

Formun deyim stmt değeri için:

throw «expr» ;

ifadenin başındaki v'nin kesin atama durumu, stmt'nin başındaki v'nin kesin atama durumuyla aynıdır.

9.4.4.13 Return deyimleri

Formun deyim stmt değeri için:

return «expr» ;
  • İfadenin başındaki v'nin kesin atama durumu, stmt'nin başındaki v'nin kesin atama durumuyla aynıdır.
  • v bir çıkış parametresiyse, kesinlikle şu iki parametreden birine atanmalıdır:
    • ifadeden sonra
    • veya deyimini finally kapsayan bir try-finallyveya try-catch-finally bloğunun sonunda.return

Formun deyim stmt değeri için:

return ;
  • v bir çıkış parametresiyse, kesinlikle şu iki parametreden birine atanmalıdır:
    • stmt öncesi
    • veya deyimini finally kapsayan bir try-finallyveya try-catch-finally bloğunun sonunda.return

9.4.4.14 Try-catch deyimleri

Formun deyim stmt değeri için:

try «try_block»
catch ( ... ) «catch_block_1»
...
catch ( ... ) «catch_block_n»
  • try_block başındaki v'ninkesin atama durumu, stmt'nin başındaki v'nin kesin atama durumuyla aynıdır.
  • v'nin catch_block_i başındaki (herhangi bir i için) kesin atama durumu, stmt'nin başındaki v'ninkesin atama durumuyla aynıdır.
  • Stmt'nin bitiş noktasındaki v'ninkesin atama durumu, v kesinlikle try_block bitiş noktasında ve hercatch_block_i (1'den n'ye kadar her i için) atanmışsa (ve yalnızca böyleyse) atanır.

9.4.4.15 Try-finally deyimleri

Formun deyim stmt değeri için:

try «try_block» finally «finally_block»
  • try_block başındaki v'ninkesin atama durumu, stmt'nin başındaki v'nin kesin atama durumuyla aynıdır.
  • finally_block başında v'nin kesin atama durumu, stmt'nin başındaki v'nin kesin atama durumuyla aynıdır.
  • Stmt'nin bitiş noktasındaki v'ninkesin atama durumu, aşağıdakilerden en az biri doğruysa (ve yalnızca bu durumda) kesinlikle atanır:
    • v kesinlikle try_block bitiş noktasına atanır
    • v kesinlikle finally_block bitiş noktasında atanır

try_block içinde goto dışında biten bir denetim akışı aktarımı (deyim gibi) yapılırsa, v finally_block bitiş noktasında kesinlikle atanmışsa, v de bu denetim akışı aktarımında kesinlikle atanmış olarak kabul edilir. (Bu, yalnızca v bu denetim akışı aktarımında başka bir nedenle atanmışsa, yine de kesinlikle atanmış olarak kabul edilir.)

9.4.4.16 Try-catch-finally deyimleri

Formun deyimi için:

try «try_block»
catch ( ... ) «catch_block_1»
...
catch ( ... ) «catch_block_n»
finally «finally_block»

tanımlayıcı atama analizi, deyimi bir deyimi kapsayantry-finallybir try-catch deyimmiş gibi yapılır:

try
{
    try «try_block»
    catch ( ... ) «catch_block_1»
    ...
    catch ( ... ) «catch_block_n»
}
finally «finally_block»

Örnek: Aşağıdaki örnek, bir try deyimin farklı bloklarının (§13.11) kesin atamayı nasıl etkilediğini gösterir.

class A
{
    static void F()
    {
        int i, j;
        try
        {
            goto LABEL;
            // neither i nor j definitely assigned
            i = 1;
            // i definitely assigned
        }
        catch
        {
            // neither i nor j definitely assigned
            i = 3;
            // i definitely assigned
        }
        finally
        {
            // neither i nor j definitely assigned
            j = 5;
            // j definitely assigned
        }
        // i and j definitely assigned
        LABEL: ;
        // j definitely assigned
    }
}

son örnek

9.4.4.17 Foreach deyimleri

Formun deyim stmt değeri için:

foreach ( «type» «identifier» in «expr» ) «embedded_statement»
  • İfadenin başındaki v'nin kesin atama durumu, stmt'nin başındaki v durumuyla aynıdır.
  • embedded_statement veya stmt'nin bitiş noktasına denetim akışı aktarımındav'ninkesin atama durumu, ifadenin sonundaki v durumuyla aynıdır.

9.4.4.18 Deyimleri kullanma

Formun deyim stmt değeri için:

using ( «resource_acquisition» ) «embedded_statement»
  • resource_acquisition başındaki v'nin kesin atama durumu, stmt'nin başındaki v durumuyla aynıdır.
  • embedded_statement denetim akışı aktarımında v'nin kesin atama durumu, resource_acquisition sonundaki v durumuyla aynıdır.

9.4.4.19 Lock deyimleri

Formun deyim stmt değeri için:

lock ( «expr» ) «embedded_statement»
  • İfadenin başındaki v'nin kesin atama durumu, stmt'nin başındaki v durumuyla aynıdır.
  • embedded_statement'a denetim akışı aktarımında v'ninkesin atama durumu, ifadenin sonundaki v durumuyla aynıdır.

9.4.4.20 Ödeme deyimleri

Formun deyim stmt değeri için:

yield return «expr» ;
  • İfadenin başındaki v'nin kesin atama durumu, stmt'nin başındaki v durumuyla aynıdır.
  • stmt'nin sonundaki v'nin kesin atama durumu, ifadenin sonundaki v durumuyla aynıdır.

Deyimin yield break kesin atama durumu üzerinde hiçbir etkisi yoktur.

9.4.4.21 Sabit ifadeler için genel kurallar

Aşağıdakiler tüm sabit ifadeler için geçerlidir ve aşağıdaki bölümlerden geçerli olabilecek tüm kurallardan önceliklidir:

değeri trueolan bir sabit ifade için:

  • v kesinlikle ifadeden önce atanmışsa, v kesinlikle ifadeden sonra atanır.
  • Aksi takdirde v ifadeden sonra "false ifadeden sonra kesinlikle atanır".

Örnek:

int x;
if (true) {}
else
{
    Console.WriteLine(x);
}

son örnek

değeri falseolan bir sabit ifade için:

  • v kesinlikle ifadeden önce atanmışsa, v kesinlikle ifadeden sonra atanır.
  • Aksi takdirde v ifadeden sonra "kesinlikle true ifadeden sonra atanır".

Örnek:

int x;
if (false)
{
    Console.WriteLine(x);
}

son örnek

Diğer tüm sabit ifadeler için, ifadeden sonra v'nin kesin atama durumu, ifadeden önceki v'nin kesin atama durumuyla aynıdır.

9.4.4.22 Basit ifadeler için genel kurallar

Aşağıdaki kural şu ifade türleri için geçerlidir: değişmez değerler (§12.8.2), basit adlar (§12.8.4), üye erişim ifadeleri (§12.8.7), dizine eklenmemiş temel erişim ifadeleri (§12.8.15), ifadeleri (§12.8.18), varsayılan değer ifadeleri (§12.8.21), ifadeleri (§12.8.23) ve bildirim ifadeleri (§12.17).

  • Böyle bir ifadenin sonundaki v'ninkesin atama durumu, ifadenin başındaki v'nin kesin atama durumuyla aynıdır.

9.4.4.23 Katıştırılmış ifadelere sahip ifadeler için genel kurallar

Aşağıdaki kurallar şu ifade türleri için geçerlidir: parantezli ifadeler (§12.8.5), demet ifadeleri (§12.8.6), öğe erişim ifadeleri (§12.8.12), dizin oluşturmalı temel erişim ifadeleri (§12.8.15), artım ve azaltma ifadeleri (§12.8.16, §12.9.6), dönüştürme ifadeleri (§12.9.7), tek +, -, ~, * ifadeleri, ikili +, -, *, /, %, <<, >>, <, <=, >, >=, ==, !=, is, as, &, |, ^ ifadeleri (§12.10, §12.11, §12.12, §12.13), bileşik atama ifadeleri (§12.21.4), checked ve unchecked ifadeleri (§12.8.20), dizi ve temsilci oluşturma ifadeleri (§12.8.17) ve await ifadeleri (§12.9.8).

Bu ifadelerin her biri, koşulsuz olarak sabit bir sırada değerlendirilen bir veya daha fazla alt ifadeye sahiptir.

Örnek: İkili % işleç, işlecin sol tarafını ve ardından sağ tarafını değerlendirir. Dizin oluşturma işlemi dizine alınan ifadeyi değerlendirir ve ardından dizin ifadelerinin her birini soldan sağa doğru sırasıyla değerlendirir. son örnek

Subexpressions expr₁, expr₂, ..., exprₓ ifade ifadeleri bu sırada değerlendirilir:

  • İfadenin başındaki v'nin kesin atama durumu, ifadenin başındaki kesin atama durumuyla aynıdır.
  • İfadenin başındaki v'nin (i büyüktür) kesin atama durumu, expri₋₁ sonundaki kesin atama durumuyla aynıdır.
  • İfadenin sonundaki v'nin kesin atama durumu, exprₓ sonundaki kesin atama durumuyla aynıdır.

9.4.4.24 Çağırma ifadeleri ve nesne oluşturma ifadeleri

Çağrılacak yöntem, kısmi yöntem bildirimi uygulamayan kısmi bir yöntemse veya çağrının atlandığı koşullu bir yöntemse (§22.5.3.2), çağırmadan sonra v'ninkesin atama durumu çağırmadan önce v'ninkesin atama durumuyla aynıdır. Aksi takdirde aşağıdaki kurallar geçerlidir:

Formun çağırma ifadesi ifadesi için:

«primary_expression» ( «arg₁», «arg₂», … , «argₓ» )

veya formun nesne oluşturma ifadesi ifade ifadeleri:

new «type» ( «arg₁», «arg₂», … , «argₓ» )
  • Çağırma ifadesi için, primary_expression önce v'nin kesin atama durumu, ifadeden önceki v durumuyla aynıdır.
  • Çağırma ifadesi için, arg₁ öncesi v'nin kesin atama durumu, primary_expression sonra v'nindurumuyla aynıdır.
  • Nesne oluşturma ifadesi için, arg₁ öncesi v'nin kesin atama durumu, ifadeden önceki v durumuyla aynıdır.
  • Her argi bağımsız değişkeni için, argi sonrasında v'nin kesin atama durumu normal ifade kuralları tarafından belirlenir ve herhangi bir in, outveya ref değiştirici yok sayılır.
  • Herhangi bir i'den büyük olan her bağımsız değişken için argi'den önce v'nin kesin atama durumu, argi₋₁ sonrasındaki v durumuyla aynıdır.
  • v değişkeni bağımsız değişken olarak geçirilirse (yani, "out out" formunun bağımsız değişkeni) bağımsız değişken olarak geçirilirse, ifadeden sonra v durumu kesinlikle atanır. Aksi takdirde, ifadeden sonra v durumu, argₓ sonrasındaki v durumuyla aynıdır.
  • Dizi başlatıcılar için (§12.8.17.5), nesne başlatıcıları (§12.8.17.3), koleksiyon başlatıcıları (§12 .8.17.4) ve anonim nesne başlatıcıları (§12.8.17.7), kesin atama durumu, bu yapıların açısından tanımlandığı genişletmeye göre belirlenir.

9.4.4.25 Basit atama ifadeleri

Bir ifadedekiatama hedefleri kümesinin aşağıdaki gibi tanımlanmasına izin verin:

  • e bir tanımlama grubu ifadesiyse, e'deki atama hedefleri, e öğelerinin atama hedeflerinin birleşimidir.
  • Aksi takdirde, e'deki atama hedefleri e'dir.

Formun ifade ifade ifadeleri için:

«expr_lhs» = «expr_rhs»
  • expr_lhs önce v'nin kesin atama durumu, ifadeden önce v'nin kesin atama durumuyla aynıdır.
  • expr_rhs önce v'nin kesin atama durumu, expr_lhs sonra v'nin kesin atama durumuyla aynıdır.
  • v, expr_lhs atama hedefiyse, ifadeden sonra v'ninkesin atama durumu kesinlikle atanır. Aksi takdirde, atama bir yapı türünün örnek oluşturucusunun içinde gerçekleşirse ve v, oluşturulan örnekte otomatik olarak uygulanan bir P özelliğinin gizli yedekleme alanıysa ve P'yi belirten bir özellik erişimi expr_lhs'nin bir tanımlama hedefiyse, ifadeden sonra v'nin kesin atama durumu kesinlikle atanır. Aksi takdirde, ifadeden sonra v'nin kesin atama durumu, expr_rhs sonra v'ninkesin atama durumuyla aynıdır.

Örnek: Aşağıdaki kodda

class A
{
    static void F(int[] arr)
    {
        int x;
        arr[x = 1] = x; // ok
    }
}

değişkeni x , ikinci basit atamanın sol tarafı olarak değerlendirildikten sonra arr[x = 1] kesinlikle atanmış olarak kabul edilir.

son örnek

9.4.4.26 & ifadeleri

Formun ifade ifade ifadeleri için:

«expr_first» && «expr_second»
  • expr_first önce v'nin kesin atama durumu, ifadeden önce v'nin kesin atama durumuyla aynıdır.
  • expr_second önce v'nin kesin atama durumu, yalnızca expr_first sonrav durumunun kesinlikle atandığı veya "true ifadeden sonra kesinlikle atandığı" durumda kesinlikle atanır. Aksi takdirde, kesinlikle atanmamış olur.
  • İfadeden sonra v'nin kesin atama durumu şu şekilde belirlenir:
    • v'nin expr_first sonrasının durumu kesinlikle atanmışsa, ifadeden sonraki v durumu kesinlikle atanır.
    • Aksi takdirde, expr_second sonra v durumu kesinlikle atanırsa ve expr_first sonra v durumu "kesinlikle yanlış ifadeden sonra atanır" ise, ifadeden sonra v durumu kesinlikle atanır.
    • Aksi takdirde, expr_second sonra v'nin durumu kesinlikle atanmışsa veya "kesinlikle true ifadeden sonra atanmışsa", ifadeden sonra v'nindurumu "kesinlikle true ifadeden sonra atanır".
    • Aksi takdirde, expr_first sonra v'nindurumu "yanlış ifadeden sonra kesinlikle atanır" ve expr_second sonra v'nindurumu "kesinlikle yanlış ifadeden sonra atanır" ise, ifadeden sonra v'nindurumu "yanlış ifadeden sonra kesinlikle atanır".
    • Aksi takdirde, ifadeden sonra v durumu kesinlikle atanmamış olur.

Örnek: Aşağıdaki kodda

class A
{
    static void F(int x, int y)
    {
        int i;
        if (x >= 0 && (i = y) >= 0)
        {
            // i definitely assigned
        }
        else
        {
            // i not definitely assigned
        }
        // i not definitely assigned
    }
}

değişkeni i , bir deyimin eklenmiş deyimlerinden if birinde kesinlikle atanmış olarak kabul edilir, ancak diğerinde atanmamış olur. yöntemindeki ifFdeyiminde, ifadenin i yürütülmesi her zaman bu katıştırılmış deyimin yürütülmesinden önce geldiği için değişkeni (i = y) kesinlikle ilk katıştırılmış deyimde atanır. Buna karşılık, değişken i ikinci katıştırılmış deyimde kesinlikle atanmamış, çünkü x >= 0 false test edilmiş olabilir ve bu da değişkenin iatanmamasıyla sonuçlanır.

son örnek

9.4.4.27 || Ifa -de

Formun ifade ifade ifadeleri için:

«expr_first» || «expr_second»
  • expr_first önce v'nin kesin atama durumu, ifadeden önce v'nin kesin atama durumuyla aynıdır.
  • expr_second önce v'nin kesin atama durumu, yalnızca expr_first sonrav durumunun kesinlikle atandığı veya "true ifadeden sonra kesinlikle atandığı" durumda kesinlikle atanır. Aksi takdirde, kesinlikle atanmamış olur.
  • İfadeden sonra v'nin kesin atama deyimi şu şekilde belirlenir:
    • v'nin expr_first sonrasının durumu kesinlikle atanmışsa, ifadeden sonraki v durumu kesinlikle atanır.
    • Aksi takdirde, expr_second sonra v'nindurumu kesinlikle atanırsa ve expr_first sonra v durumu "kesinlikle doğru ifadeden sonra atanır" ise, ifadeden sonra v'nindurumu kesinlikle atanır.
    • Aksi takdirde, expr_second sonra v'nin durumu kesinlikle atanırsa veya "yanlış ifadeden sonra kesinlikle atanır" ise, ifadeden sonra v'nindurumu "yanlış ifadeden sonra kesinlikle atanır".
    • Aksi takdirde, expr_first sonra v'nindurumu "kesinlikle true ifadeden sonra atanır" ve expr_ saniye sonra v'nindurumu "kesinlikle true ifadeden sonra atanır" ise, ifadeden sonra v'nin durumu "true ifadeden sonra kesinlikle atanır".
    • Aksi takdirde, ifadeden sonra v durumu kesinlikle atanmamış olur.

Örnek: Aşağıdaki kodda

class A
{
    static void G(int x, int y)
    {
        int i;
        if (x >= 0 || (i = y) >= 0)
        {
            // i not definitely assigned
        }
        else
        {
            // i definitely assigned
        }
        // i not definitely assigned
    }
}

değişkeni i , bir deyimin eklenmiş deyimlerinden if birinde kesinlikle atanmış olarak kabul edilir, ancak diğerinde atanmamış olur. yöntemindeki ifGdeyiminde, ifadenin i yürütülmesi her zaman bu katıştırılmış deyimin yürütülmesinden önce geldiği için değişkeni (i = y) kesinlikle ikinci katıştırılmış deyimde atanır. Buna karşılık, değişkeni i kesinlikle ilk katıştırılmış deyimde atanmamış, çünkü x >= 0 true'yu test etmiş ve değişkenin iatanmamış olmasına neden olmuş olabilir.

son örnek

9.4.4.28 ! ifadeler

Formun ifade ifade ifadeleri için:

! «expr_operand»
  • expr_operand önce v'nin kesin atama durumu, ifadeden önce v'nin kesin atama durumuyla aynıdır.
  • İfadeden sonra v'nin kesin atama durumu şu şekilde belirlenir:
    • expr_operand sonrasının vdurumu kesinlikle atanmışsa, ifade sonrası vdurumu kesinlikle atanır.
    • Aksi takdirde, expr_operand sonrasının vdurumu "yanlış ifadeden sonra kesinlikle atanır" ise, ifadevdurumu "kesinlikle doğru ifadeden sonra atanır".
    • Aksi takdirde, expr_operandvdurumu "kesinlikle true ifadeden sonra atanır" ise, ifadeden sonra v'nin durumu "false ifadeden sonra kesinlikle atanır".
    • Aksi takdirde, ifade sonrası vdurumu kesinlikle atanmamış olur.

9.4.4.29 ?? ifadeler

Formun ifade ifade ifadeleri için:

«expr_first» ?? «expr_second»
  • expr_first önce v'nin kesin atama durumu, ifadeden önce v'nin kesin atama durumuyla aynıdır.
  • expr_second önce v'ninkesin atama durumu, expr_first sonra v'nin kesin atama durumuyla aynıdır.
  • İfadeden sonra v'nin kesin atama deyimi şu şekilde belirlenir:
    • expr_firstnull, ifadeden sonraki v durumu, expr_second sonra v'nin durumuyla aynıdır.
    • Aksi takdirde, ifadeden sonra v'nindurumu, expr_first sonra v'ninkesin atama durumuyla aynıdır.

9.4.4.30 ?: ifadeler

Formun ifade ifade ifadeleri için:

«expr_cond» ? «expr_true» : «expr_false»
  • expr_cond önce v'nin kesin atama durumu, ifadeden önceki v durumuyla aynıdır.
  • expr_true önce v'nin kesin atama durumu, expr_cond sonrav'nin durumu kesinlikle atanmışsa veya "true ifadeden sonra kesinlikle atanmışsa" kesinlikle atanır.
  • expr_false önce v'nin kesin atama durumu, v'nin expr_cond sonrasının durumu kesinlikle atanmışsa veya "false ifadeden sonra kesinlikle atanmışsa" kesinlikle atanır.
  • İfadeden sonra v'nin kesin atama durumu şu şekilde belirlenir:
    • expr_cond değeri olan bir sabit ifadeyse (true), ifadeden sonraki v durumu, expr_true sonra v durumuyla aynıdır.
    • Aksi takdirde, expr_cond değeri olan bir sabit ifade (§12.23) ise ifadeden sonraki vfalse, expr_false sonra v durumuyla aynıdır.
    • Aksi takdirde, expr_true sonra v durumu kesinlikle atanırsa ve expr_false sonra v durumu kesinlikle atanırsa, ifadeden sonra v durumu kesinlikle atanır.
    • Aksi takdirde, ifadeden sonra v durumu kesinlikle atanmamış olur.

9.4.4.31 Anonim işlevler

Gövde (blok veya ifade) gövdesi olan bir lambda_expression veya anonymous_method_expressionifade için:

  • Bir parametrenin kesin atama durumu, adlandırılmış bir yöntemin parametresiyle aynıdır (§9.2.6, §9.2.7, §9.2.8).
  • Dış değişkenin v gövdeden önceki kesin atama durumu, ifadeden önceki v durumuyla aynıdır. Yani, dış değişkenlerin kesin atama durumu anonim işlevin bağlamından devralınır.
  • İfadeden sonra v dış değişkenininkesin atama durumu, ifadeden önceki v durumuyla aynıdır.

Örnek: Örnek

class A
{
    delegate bool Filter(int i);
    void F()
    {
        int max;
        // Error, max is not definitely assigned
        Filter f = (int n) => n < max;
        max = 5;
        DoWork(f);
    }
    void DoWork(Filter f) { ... }
}

anonim işlevin bildirildiği yerde max değeri kesinlikle atanmadığından derleme zamanı hatası oluşturur.

son örnek

Örnek: Örnek

class A
{
    delegate void D();
    void F()
    {
        int n;
        D d = () => { n = 1; };
        d();
        // Error, n is not definitely assigned
        Console.WriteLine(n);
    }
}

ayrıca anonim işlevdeki atamanın n anonim işlevin dışındaki kesin atama durumunu n etkilemediğinden derleme zamanı hatası oluşturur.

son örnek

9.4.4.32 Throw ifadeleri

Formun ifade ifade ifadeleri için:

throw thrown_expr

  • thrown_expr önce v'nin kesin atama durumu, ifadeden önceki v durumuyla aynıdır.
  • İfadeden sonra v'nin kesin atama durumu "kesinlikle atanır".

9.4.4.33 Yerel işlevlerdeki değişkenler için kurallar

Yerel işlevler, üst yöntemleri bağlamında analiz edilir. Yerel işlevler için önemli olan iki denetim akışı yolu vardır: işlev çağrıları ve temsilci dönüştürmeleri.

Her yerel işlevin gövdesi için kesin atama, her çağrı sitesi için ayrı ayrı tanımlanır. Her çağrıda, yerel işlev tarafından yakalanan değişkenler kesinlikle çağrı noktasında atanmışsa kesinlikle atanmış olarak kabul edilir. Bu noktada yerel işlev gövdesi için de bir denetim akışı yolu vardır ve erişilebilir olarak kabul edilir. Yerel işleve yapılan bir çağrıdan sonra, işlevdenreturn ayrılan her denetim noktasında (deyimler, deyimler, yieldawait ifadeler) kesinlikle atanmış olan yakalanan değişkenler, çağrı konumundan sonra kesinlikle atanmış olarak kabul edilir.

Temsilci dönüştürmeleri, yerel işlev gövdesine yönelik bir denetim akışı yoluna sahiptir. Yakalanan değişkenler, dönüştürmeden önce kesinlikle atandıysa gövde için kesinlikle atanır. Yerel işlev tarafından atanan değişkenler dönüştürmeden sonra atanmış olarak kabul edilmez.

Not: Yukarıdaki, gövdelerin her yerel işlev çağrısında veya temsilci dönüştürmesinde kesin atama için yeniden çözümlendiğini gösterir. Derleyicilerin her çağrıda veya temsilci dönüştürmede yerel işlevin gövdesini yeniden çözümlemesi gerekmez. Uygulamanın bu açıklamaya eşdeğer sonuçlar üretmesi gerekir. son not

Örnek: Aşağıdaki örnekte, yerel işlevlerde yakalanan değişkenler için kesin atama gösterilmektedir. Bir yerel işlev yakalanan bir değişkeni yazmadan önce okursa, yakalanan değişkenin yerel işlevi çağırmadan önce kesinlikle atanması gerekir. Yerel işlev F1 , atamadan okur s . Bu, kesinlikle atanmadan önce F1 çağrılırsa s bir hatadır. F2 i okumadan önce atar. Kesinlikle atanmadan önce i çağrılabilir. Ayrıca, F3 içinde kesinlikle atandığından F2s2sonra F2 çağrılabilir.

void M()
{
    string s;
    int i;
    string s2;
   
    // Error: Use of unassigned local variable s:
    F1();
    // OK, F2 assigns i before reading it.
    F2();
    
    // OK, i is definitely assigned in the body of F2:
    s = i.ToString();
    
    // OK. s is now definitely assigned.
    F1();

    // OK, F3 reads s2, which is definitely assigned in F2.
    F3();

    void F1()
    {
        Console.WriteLine(s);
    }
    
    void F2()
    {
        i = 5;
        // OK. i is definitely assigned.
        Console.WriteLine(i);
        s2 = i.ToString();
    }

    void F3()
    {
        Console.WriteLine(s2);
    }
}

son örnek

9.4.4.34 is-pattern ifadeleri

Formun ifade ifade ifadeleri için:

expr_operand desendir

  • expr_operand önce v'nin kesin atama durumu, ifadeden önce v'nin kesin atama durumuyla aynıdır.
  • 'v' değişkeni desende bildirilirse, ifadeden sonra 'v' kesin atama durumu "true olduğunda kesinlikle atanır".
  • Aksi takdirde ifadeden sonra 'v' kesin atama durumu, expr_operand sonra 'v' kesin atama durumuyla aynıdır.

9.5 Değişken başvuruları

variable_reference, değişken olarak sınıflandırılan bir ifadedir. variable_reference, hem geçerli değeri getirmek hem de yeni bir değer depolamak için erişilebilen bir depolama konumunu belirtir.

variable_reference
    : expression
    ;

Not: C ve C++'da variable_reference lvalue olarak bilinir. son not

9.6 Değişken başvurularının bölünmezliği

Aşağıdaki veri türlerinin okuma ve yazma işlemleri atomik olmalıdır: , , , , , , boolchar, , bytesbyteve başvuru türleri. shortushortuintintfloat Ayrıca, önceki listede temel alınan bir türe sahip sabit listesi türlerinin okuma ve yazma işlemleri de atomik olmalıdır. Kullanıcı tanımlı türlerin yanı sıra , long, ulongve gibi doublediğer türlerin okuma ve decimalyazma işlemleri atomik olmamalıdır. Bu amaçla tasarlanmış kitaplık işlevlerinin yanı sıra, artış veya azaltma gibi atomik okuma-değiştirme-yazma garantisi yoktur.

9.7 Başvuru değişkenleri ve dönüşleri

9.7.1 Genel

Başvuru değişkeni, başvuran (§9.2.6) olarak adlandırılan başka bir değişkene başvuran değişkendir. Başvuru değişkeni, değiştirici ile ref bildirilen yerel bir değişkendir.

Başvuru değişkeni, bir variable_reference (§9,5) başvuranın değerine değil, başvurana depolar. Bir değerin gerekli olduğu bir başvuru değişkeni kullanıldığında, başvuran değeri döndürülür; benzer şekilde, başvuru değişkeni bir atamanın hedefi olduğunda, atandığı başvurudur. Başvuru değişkeninin başvurduğu değişken, yani başvuran için depolanan variable_reference , başvuru ataması (= ref) kullanılarak değiştirilebilir.

Örnek: Aşağıdaki örnekte, başvuranı bir dizinin öğesi olan bir yerel başvuru değişkeni gösterilmektedir:

public class C
{
    public void M()
    {
        int[] arr = new int[10];
        // element is a reference variable that refers to arr[5]
        ref int element = ref arr[5];
        element += 5; // arr[5] has been incremented by 5
    }     
}

son örnek

Başvuru dönüşü, bir başvuruya göre dönüş yönteminden (§15.6.1) döndürülen variable_reference. Bu variable_reference , başvuru dönüşünün başvuranıdır.

Örnek: Aşağıdaki örnek, başvuranı bir dizi alanının öğesi olan bir başvuru dönüşünü gösterir:

public class C
{
    private int[] arr = new int[10];

    public ref readonly int M()
    {
        // element is a reference variable that refers to arr[5]
        ref int element = ref arr[5];
        return ref element; // return reference to arr[5];
    }     
}

son örnek

9.7.2 Başvuru güvenli bağlamları

9.7.2.1 Genel

Tüm başvuru değişkenleri, başvuru değişkeninin ref-safe-context değerinin başvuranın ref-safe-context değerinden büyük olmamasını sağlayan güvenlik kurallarına uyar.

Not: Güvenli bağlamın ilgili kavramı, ilişkili kısıtlamalarla birlikte (§16.4.12) içinde tanımlanır. son not

Herhangi bir değişken için, bu değişkenin ref-safe bağlamı, bu değişkene variable_reference (§9,5) geçerli olduğu bağlamdır. Bir başvuru değişkeninin başvurusu, başvuru değişkeninin kendisi kadar en az ref-safe bağlamı kadar geniş bir ref-safe-context'a sahip olmalıdır.

Not: Derleyici, program metninin statik analizi aracılığıyla ref-safe-context öğesini belirler. Ref-safe bağlamı, bir değişkenin çalışma zamanındaki ömrünü yansıtır. son not

Üç ref-safe bağlamı vardır:

  • bildirim bloğu: Bir variable_reference yerel değişkene (§9.2.9.1) güvenli bağlamı, bu kapsamdaki iç içe yerleştirilmiş katıştırılmış deyimdahil olmak üzere yerel değişkenin kapsamıdır (§13.6.2).

    Yerel değişkene variable_reference , yalnızca başvuru değişkeni bu değişkenin ref-safe-bağlamı içinde bildirilirse başvuru değişkeni için geçerli bir başvurudur.

  • function-member: İşlev içinde, aşağıdakilerden herhangi birine variable_reference işlev-üyesinin ref-safe-bağlamı vardır:

    • Bir işlev üyesi bildiriminde sınıf üyesi işlevlerinin örtük değeri dahil olmak üzere değer parametreleri (this) ve
    • Yapı üyesi işlevinin örtük başvuru (ref) parametresi (§15.6.2.3.3) this ve alanları.

    İşlev-üyesinin ref-safe-context değerine sahip bir variable_reference, yalnızca başvuru değişkeni aynı işlev üyesinde bildirildiğinde geçerli bir başvurudur.

  • çağıran bağlamı: İşlev içinde, aşağıdakilerden herhangi birine variable_reference çağıran bağlamının ref-safe bağlamı vardır:

    • Yapı üyesi işlevinin örtük değeri dışındaki başvuru parametreleri (this);
    • Bu tür parametrelerin üye alanları ve öğeleri;
    • Sınıf türü parametrelerinin üye alanları; ve
    • Dizi türü parametrelerinin öğeleri.

Çağıran bağlamının ref-safe-context içeren bir variable_reference, başvuru dönüşünün başvuranı olabilir.

Bu değerler, en dardan (bildirim bloğu) en genişe (çağıran bağlamı) iç içe bir ilişki oluşturur. İç içe yerleştirilmiş her blok farklı bir bağlamı temsil eder.

Örnek: Aşağıdaki kod, farklı ref-safe-contexts örneklerini gösterir. Bildirimler, bir değişkenin başlatma ifadesi ref olması için başvuruda bulunanın ref-safe-bağlamını gösterir. Örneklerde bir başvuru dönüş için ref-safe-context gösterilmektedir:

public class C
{
    // ref safe context of arr is "caller-context". 
    // ref safe context of arr[i] is "caller-context".
    private int[] arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

    // ref safe context is "caller-context"
    public ref int M1(ref int r1)
    {
        return ref r1; // r1 is safe to ref return
    }

    // ref safe context is "function-member"
    public ref int M2(int v1)
    {
        return ref v1; // error: v1 isn't safe to ref return
    }

    public ref int M3()
    {
        int v2 = 5;

        return ref arr[v2]; // arr[v2] is safe to ref return
    }

    public void M4(int p) 
    {
        int v3 = 6;

        // context of r2 is declaration-block,
        // ref safe context of p is function-member
        ref int r2 = ref p;

        // context of r3 is declaration-block,
        // ref safe context of v3 is declaration-block
        ref int r3 = ref v3;

        // context of r4 is declaration-block,
        // ref safe context of arr[v3] is caller-context
        ref int r4 = ref arr[v3]; 
    }
}

bitiş örneği.

Örnek: Türler için struct örtük this parametre bir başvuru parametresi olarak geçirilir. bir türün alanlarının struct işlev-üyesi olarak ref-safe bağlamı, bu alanların başvuru dönüşlerine göre döndürülmesini engeller. Bu kural aşağıdaki kodu engeller:

public struct S
{
     private int n;

     // Disallowed: returning ref of a field.
     public ref int GetN() => ref n;
}

class Test
{
    public ref int M()
    {
        S s = new S();
        ref int numRef = ref s.GetN();
        return ref numRef; // reference to local variable 'numRef' returned
    }
}

bitiş örneği.

9.7.2.2 Yerel değişken başvuru güvenli bağlamı

Yerel değişken viçin:

  • Bir başvuru değişkeniyse v , başv-safe-bağlamı, başlatma ifadesinin ref-safe-context değeriyle aynıdır.
  • Aksi takdirde ref-safe-context, bildirim bloğudur.

9.7.2.3 Parametre başvurusu güvenli bağlamı

Bir parametre piçin:

  • Başvuru veya giriş parametresiyse p , ref-safe-context çağıran bağlamıdır. Bir giriş parametresiyse p , yazılabilir ref olarak döndürülemez, ancak olarak ref readonlydöndürülebilir.
  • Bir çıkış parametresiyse p , ref-safe-context çağıran bağlamıdır.
  • Aksi takdirde, bir yapı türünün parametresiyse pthis , ref-safe-context işlevi-üyesidir.
  • Aksi takdirde parametresi bir değer parametresidir ve ref-safe-context işlevin üyesidir.

9.7.2.4 Alan başvurusu güvenli bağlamı

Bir alana başvuru gösteren bir değişken için: e.F

  • Başvuru türündeyse e , ref-safe-context çağıran bağlamıdır.
  • Aksi takdirde, bir değer türündeyse e , ref-safe-context değeri ile ref-safe-context aynıdır e.

9.7.2.5 İşleçleri

Koşullu işleç (§12.18), c ? ref e1 : ref e2ve başvuru atama işleci = ref e (§12.21.1) işlenen olarak başvuru değişkenlerine sahiptir ve bir başvuru değişkeni verir. Bu işleçler için sonucun ref-safe bağlamı, tüm ref işlenenlerin ref-safe bağlamları arasındaki en dar bağlamdır.

9.7.2.6 İşlev çağrısı

Başvuru döndüren işlev çağrısından kaynaklanan bir değişken c için, ref-safe-context aşağıdaki bağlamların en darıdır:

  • Arayan bağlamı.
  • Tüm ref, outve in bağımsız değişken ifadelerinin (alıcı hariç) ref-safe bağlamı.
  • Her giriş parametresi için, değişken olan karşılık gelen bir ifade varsa ve değişkenin türü ile parametrenin türü arasında bir kimlik dönüştürmesi varsa, değişkenin ref-safe-context değeri, aksi takdirde en yakın kapsayan bağlam.
  • Tüm bağımsız değişken ifadelerinin (alıcı dahil) güvenli bağlamı (§16.4.12).

Örnek: Son madde işareti, aşağıdaki gibi kodu işlemek için gereklidir:

ref int M2()
{
    int v = 5;
    // Not valid.
    // ref safe context of "v" is block.
    // Therefore, ref safe context of the return value of M() is block.
    return ref M(ref v);
}

ref int M(ref int p)
{
    return ref p;
}

son örnek

Bir özellik çağırması ve dizin oluşturucu çağrısı ( get veya set) yukarıdaki kurallar tarafından temel alınan erişimcinin işlev çağrısı olarak değerlendirilir. Yerel işlev çağırma, işlev çağırmadır.

9.7.2.7 Değerleri

Değerin ref-safe bağlamı en yakın kapsayan bağlamdır.

Not: Bu, türünde M(ref d.Length)olduğu gibi d bir çağrıda dynamic oluşur. Giriş parametrelerine karşılık gelen bağımsız değişkenlerle de tutarlıdır. son not

9.7.2.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 yöntem çağrısıyla (§9.7.2.6) aynı kurallara uyar.

9.7.2.9 Başvuru değişkenlerinde sınırlamalar

  • Ne bir başvuru parametresi, ne bir çıkış parametresi, ne bir giriş parametresi, ne yerel ref , ne de bir ref struct tür parametresi ya da yerel lambda ifadesi veya yerel işlevi tarafından yakalanır.
  • Ne bir başvuru parametresi, ne bir çıkış parametresi, ne de bir giriş parametresi, ne de bir ref struct tür parametresi yineleyici yöntemi veya yöntemi için bağımsız async değişken olamaz.
  • ref Bir deyimin veya ref struct ifadenin bağlamında ne yerel ne de bir yield return türün yereli await olamaz.
  • Bir başvuru yeniden ataması e1 = ref e2için, 'nin e2 ref-safe-context değeri en az ref-safe-context kadar geniş bir bağlame1olmalıdır.
  • Ref dönüş deyimi return ref e1için, ref-safe-context e1 , çağıran bağlamı olmalıdır.