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 vei
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_elementout
gerç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:
- bir value_type değişkeni için varsayılan değer, value_type varsayılan oluşturucusunun (§8.3.3) hesapladığı değerle aynıdır.
- bir reference_type değişkeni için varsayılan değerdir
null
.
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
deyimindeforeach
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 veyaforeach
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
bool
bir 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.
- , , , , , ,
block
checked
unchecked
if
while
do
veyafor
deyiminin bitiş noktasındaki v'ninforeach
lock
, bu deyimin bitiş noktasını hedefleyen tüm denetim akışı aktarımlarında v'ninusing
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 b
case 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 goto
hedefleyen deyimlerle.LLoop
for_condition deyiminden atlanırsa, yukarıdaki genişletmede for_conditionfor
kesin atama değerlendirmesi devam eder.
9.4.4.11 Break, continue ve goto deyimleri
, veya deyiminin break
kesin atama durumu, continue
deyiminin 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 birtry
-finally
veyatry
-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 birtry
-finally
veyatry
-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
-finally
bir 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 true
olan 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 false
olan 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 (
- 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
,out
veyaref
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 sonraarr[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ş deyimlerindenif
birinde kesinlikle atanmış olarak kabul edilir, ancak diğerinde atanmamış olur. yöntemindekiif
F
deyiminde, ifadenini
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şkeni
ikinci katıştırılmış deyimde kesinlikle atanmamış, çünküx >= 0
false test edilmiş olabilir ve bu da değişkenini
atanmaması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ş deyimlerindenif
birinde kesinlikle atanmış olarak kabul edilir, ancak diğerinde atanmamış olur. yöntemindekiif
G
deyiminde, ifadenini
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şkenii
kesinlikle ilk katıştırılmış deyimde atanmamış, çünküx >= 0
true'yu test etmiş ve değişkenini
atanmamış 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
v
durumu kesinlikle atanmışsa, ifade sonrasıv
durumu kesinlikle atanır. - Aksi takdirde, expr_operand sonrasının
v
durumu "yanlış ifadeden sonra kesinlikle atanır" ise, ifadev
durumu "kesinlikle doğru ifadeden sonra atanır". - Aksi takdirde, expr_operand
v
durumu "kesinlikle true ifadeden sonra atanır" ise, ifadeden sonra v'nin durumu "false ifadeden sonra kesinlikle atanır". - Aksi takdirde, ifade sonrası
v
durumu kesinlikle atanmamış olur.
- expr_operand sonrasının
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_first
null
, 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.
- expr_first
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 v
false
, 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.
-
expr_cond değeri olan bir sabit ifadeyse (
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 durumunun
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, yield
await
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 okurs
. Bu, kesinlikle atanmadan önceF1
çağrılırsas
bir hatadır.F2
i
okumadan önce atar. Kesinlikle atanmadan öncei
çağrılabilir. Ayrıca,F3
içinde kesinlikle atandığındanF2
s2
sonraF2
ç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: , , , , , , bool
char
, , byte
sbyte
ve başvuru türleri. short
ushort
uint
int
float
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
, ulong
ve gibi double
diğer türlerin okuma ve decimal
yazma 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.
- Bir işlev üyesi bildiriminde sınıf üyesi işlevlerinin örtük değeri dahil olmak üzere değer parametreleri (
ç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:
Ç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ükthis
parametre bir başvuru parametresi olarak geçirilir. bir türün alanlarınınstruct
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 v
iç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 p
için:
- Başvuru veya giriş parametresiyse
p
, ref-safe-context çağıran bağlamıdır. Bir giriş parametresiysep
, yazılabilirref
olarak döndürülemez, ancak olarakref readonly
dö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
p
this
, 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ıre
.
9.7.2.5 İşleçleri
Koşullu işleç (§12.18), c ? ref e1 : ref e2
ve 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
,out
vein
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 gibid
bir çağrıdadynamic
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 birref 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ızasync
değişken olamaz. -
ref
Bir deyimin veyaref struct
ifadenin bağlamında ne yerel ne de biryield return
türün yereliawait
olamaz. - Bir başvuru yeniden ataması
e1 = ref e2
için, 'nine2
ref-safe-context değeri en az ref-safe-context kadar geniş bir bağlame1
olmalıdır. - Ref dönüş deyimi
return ref e1
için, ref-safe-contexte1
, çağıran bağlamı olmalıdır.
ECMA C# draft specification