Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
9.1 Általános
A változók a tárolási helyeket jelölik. Minden változónak van egy típusa, amely meghatározza, hogy milyen értékek tárolhatók a változóban. A C# egy típusbiztos nyelv, a C# fordító pedig garantálja, hogy a változókban tárolt értékek mindig a megfelelő típusúak legyenek. A változó értéke a hozzárendeléssel vagy az ++ operátorok -- használatával módosítható.
A változót mindenképpen ki kell osztani (9.4. §) az értékének megszerzése előtt.
A következő alklámokban leírtak szerint a változók kezdetben hozzárendelve vagy kezdetben nem lesznek hozzárendelve. Az eredetileg hozzárendelt változóknak van egy jól definiált kezdeti értéke, és mindig határozottan hozzárendeltnek számítanak. Az eredetileg nem hozzárendelt változóknak nincs kezdeti értéke. Ahhoz, hogy egy eredetileg hozzárendeletlen változót biztosan hozzárendeltnek lehessen tekinteni egy adott helyen, a változóhoz való hozzárendelésnek minden lehetséges végrehajtási útvonalon meg kell történnie, amely az adott helyre vezet.
9.2 Változókategóriák
9.2.1 Általános
A C# nyolc változókategóriát határoz meg: statikus változókat, példányváltozókat, tömbelemeket, értékparamétereket, bemeneti paramétereket, referenciaparamétereket, kimeneti paramétereket és helyi változókat. Az alábbi alklámok ezen kategóriák mindegyikét ismertetik.
Példa: Az alábbi kódban
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; } }
xstatikus változó,ypéldányváltozó,v[0]tömbelem,aértékparaméter,breferenciaparaméter,ckimeneti paraméter,dbemeneti paraméter, helyiiváltozó. záró példa
9.2.2 Statikus változók
A módosítóval static deklarált mező statikus változó. A statikus változó a konstruktor (static.§) végrehajtása előtt jön létre, és a kapcsolódó alkalmazástartomány megszűnésekor megszűnik.
A statikus változó kezdeti értéke a változó típusának alapértelmezett értéke (9.3. §).
A végleges hozzárendelés ellenőrzése céljából egy statikus változót először hozzárendeltnek tekintünk.
9.2.3 Példányváltozók
9.2.3.1 Általános
A módosító nélkül static deklarált mező egy példányváltozó.
9.2.3.2 Példányváltozók osztályokban
Egy osztály példányváltozója akkor jön létre, amikor létrejön az adott osztály új példánya, és megszűnik, ha nincs hivatkozás az adott példányra, és a példány véglegesítője (ha van ilyen) végrehajtva.
Egy osztály példányváltozójának kezdeti értéke a változó típusának alapértelmezett értéke (9.3. §).
A határozott hozzárendelés ellenőrzése céljából az osztály példányváltozóját kezdetben hozzárendeltnek tekintjük.
9.2.3.3 Példányváltozók a szerkezetekben
Egy szerkezet példányváltozójának élettartama pontosan megegyezik azzal a szerkezetváltozóval, amelyhez tartozik. Más szóval, ha egy strukturált típusú változó létrejön vagy megszűnik, akkor a szerkezet példányváltozói is.
A szerkezet példányváltozójának kezdeti hozzárendelési állapota megegyezik az azt tartalmazó struct változó állapotával. Más szóval, ha egy szerkezetváltozót kezdetben hozzárendeltnek tekintenek, akkor a példányváltozók is, és ha egy strukturált változót eredetileg nem hozzárendeltnek tekintenek, a példányváltozók hasonlóképpen nem lesznek hozzárendelve.
9.2.4 Tömbelemek
A tömb elemei egy tömbpéldány létrehozásakor jönnek létre, és megszűnnek, ha nincs hivatkozás az adott tömbpéldányra.
A tömb egyes elemeinek kezdeti értéke a tömbelemek típusának alapértelmezett értéke (9.3. §).
A végleges hozzárendelés ellenőrzése céljából a tömbelem kezdetben hozzárendeltnek minősül.
9.2.5 Értékparaméterek
Az értékparaméter a függvénytag (metódus, példánykonstruktor, tartozék vagy operátor) vagy névtelen függvény meghívásával jön létre, amelyhez a paraméter tartozik, és inicializálva lesz a meghívásban megadott argumentum értékével. Az értékparaméter általában megszűnik, amikor a függvény törzsének végrehajtása befejeződik. Ha azonban az értékparamétert nemstatic névtelen függvény rögzíti (12.22.6.2.2. §), élettartama legalább addig tart, amíg a névtelen függvényből létrehozott delegált vagy kifejezésfa jogosult a szemétgyűjtésre.
A határozott hozzárendelés ellenőrzése céljából egy értékparamétert elsőként hozzárendeltnek tekintünk.
Az értékparamétereket a 15.6.2.2.
9.2.6 Referenciaparaméterek
A referenciaparaméter egy referenciaváltozó (§9.7), amely a függvény tagjának, delegáltjának, névtelen függvényének vagy helyi függvényének meghívása után jön létre, és annak hivatkozását inicializálja a meghívás argumentumaként megadott változóra. A függvény törzsének végrehajtása után megszűnik a referenciaparaméter. Az értékparaméterekkel ellentétben a referenciaparaméter nem rögzíthető (9.7.2.9. §).
A referenciaparaméterekre az alábbi határozott hozzárendelési szabályok vonatkoznak.
Megjegyzés: A kimeneti paraméterekre vonatkozó szabályok eltérőek, és azokat a (9.2.7. §)-ban ismertetjük. végjegyzet
- A változót mindenképpen hozzárendelni kell (9.4. §), mielőtt referenciaparaméterként átadható egy függvénytagban vagy meghatalmazotti meghívásban.
- Egy függvénytagon vagy névtelen függvényen belül a rendszer először hozzárendeltnek tekint egy referenciaparamétert.
A referenciaparamétereket a 15.6.2.3.3.
9.2.7 Kimeneti paraméterek
A kimeneti paraméter egy referenciaváltozó (§9.7), amely a függvény tagjának, delegáltjának, névtelen függvényének vagy helyi függvényének meghívása után jön létre, és annak hivatkozását inicializálja a meghívás argumentumaként megadott változóra. A kimeneti paraméter megszűnik, amikor a függvény törzsének végrehajtása befejeződik. Az értékparaméterekkel ellentétben a kimeneti paraméter nem rögzíthető (9.7.2.9. §).
A kimeneti paraméterekre az alábbi határozott hozzárendelési szabályok vonatkoznak.
Megjegyzés: A referenciaparaméterekre vonatkozó szabályok eltérőek, és azokat a (9.2.6. §) ismerteti. végjegyzet
- A változót nem kell feltétlenül hozzárendelni ahhoz, hogy kimeneti paraméterként átadható legyen egy függvénytagban vagy delegált meghívásban.
- A függvénytagok vagy delegáltak meghívásának normál befejezését követően a kimeneti paraméterként átadott változók az adott végrehajtási útvonalon lesznek hozzárendelve.
- Egy függvénytagon vagy névtelen függvényen belül a kimeneti paraméter kezdetben nincs hozzárendelve.
- A függvénytagok, névtelen függvények vagy helyi függvények minden kimeneti paraméterét határozottan hozzárendelni kell (9.4. §), mielőtt a függvénytag, a névtelen függvény vagy a helyi függvény normálisan visszatér.
A kimeneti paramétereket a 15.6.2.3.4.
9.2.8 Bemeneti paraméterek
A bemeneti paraméter egy referenciaváltozó (§9.7), amely a függvény tagjának, delegáltjának, névtelen függvényének vagy helyi függvényének meghívásakor jön létre, és annak hivatkozását inicializálja a meghívás argumentumaként megadott variable_reference . A függvény törzsének végrehajtása után megszűnik egy bemeneti paraméter. Az értékparaméterekkel ellentétben a bemeneti paraméter nem rögzíthető (9.7.2.9. §).
A bemeneti paraméterekre az alábbi határozott hozzárendelési szabályok vonatkoznak.
- A változót mindenképpen hozzárendelni kell (9.4. §), mielőtt bemeneti paraméterként átadható egy függvénytagban vagy meghatalmazotti meghívásban.
- Egy függvénytagon, névtelen függvényen vagy helyi függvényen belül a bemeneti paraméter kezdetben hozzárendeltnek minősül.
A bemeneti paramétereket a 15.6.2.3.2.
9.2.9 Helyi változók
9.2.9.1 Általános
A helyi változókategy try_statement local_variable_declaration, declaration_expression, foreach_statement vagy specific_catch_clausedeklarálja. A helyi változók deklarálhatók bizonyos típusú mintákkal is (11. §). Egy foreach_statement esetében a helyi változó egy iterációs változó (13.9.5. §). Egy specific_catch_clause esetében a helyi változó kivételváltozó (13.11. §). Egy foreach_statement vagy specific_catch_clause által deklarált helyi változó kezdetben hozzárendeltnek minősül.
A local_variable_declaration blokkokban, for_statement, switch_block vagy using_statement fordulhatnak elő. A declaration_expressionout és tuple_element is előfordulhat, amely egy dekonstruálási feladat célja (12.24.2. §).
A helyi változó élettartama a program végrehajtásának az a része, amelynek során a tárterület garantáltan lefoglalva lesz. Ez az élettartam a hatókörbe való belépéstől, amelyhez társítva van, legalább addig tart, amíg a hatókör végrehajtása valamilyen módon véget nem ér. (Egy zárt blokk beírása, metódus meghívása vagy egy iterátorblokkból származó érték megadása felfüggeszti, de nem fejeződik be az aktuális hatókör végrehajtásával.) Ha a helyi változót nemstatic névtelen függvény rögzíti (12.22.6.2. §), élettartama legalább addig tart, amíg a névtelen függvényből létrehozott delegált vagy kifejezésfa, valamint a rögzített változóra hivatkozó egyéb objektumok nem jogosultak szemétgyűjtésre. Ha a szülő hatókör rekurzív vagy iteratív módon van megadva, a rendszer minden alkalommal létrehoz egy új helyi változópéldányt, és minden alkalommal kiértékeli annak inicializálóját.
Megjegyzés: A rendszer minden alkalommal példányosít egy helyi változót, amikor be van írva a hatóköre. Ez a viselkedés a névtelen metódusokat tartalmazó felhasználói kódban látható. végjegyzet
Megjegyzés: Az foreach_statement által deklarált iterációs változó (13.9.5. §) élettartama az adott utasítás egyetlen iterációja. Minden iteráció létrehoz egy új változót. végjegyzet
Megjegyzés: Egy helyi változó tényleges élettartama implementációfüggő. Egy fordító például statikusan megállapíthatja, hogy egy blokk helyi változója csak a blokk egy kis részére használható. Ezzel az elemzéssel a fordító olyan kódot hozhat létre, amely a változó tárolójának rövidebb élettartamát eredményezi, mint a blokk.
A helyi referenciaváltozó által hivatkozott tárolót a rendszer a helyi referenciaváltozó élettartamától függetlenül visszanyeri (7.9. §).
végjegyzet
A local_variable_declaration vagy declaration_expression által bevezetett helyi változók nem inicializálódnak automatikusan, így nincs alapértelmezett érték. Az ilyen helyi változók kezdetben nem hozzárendeltnek minősülnek.
Megjegyzés: Az inicializálót tartalmazó local_variable_declaration kezdetben még nincs hozzárendelve. A deklaráció végrehajtása pontosan úgy viselkedik, mint a változó hozzárendelése (9.4.4.5. §). Változó használata az inicializáló végrehajtása előtt; például az inicializáló kifejezésen belül, vagy az inicializálót megkerülő goto_statement használatával; fordítási időhiba:
goto L; int x = 1; // never executed L: x += 1; // error: x not definitely assignedA helyi változó hatókörén belül fordítási idejű hiba az adott helyi változóra hivatkozni a deklarátort megelőző szöveges pozícióban.
végjegyzet
9.2.9.2 Elvetések
Az elvetés egy helyi változó, amelynek nincs neve. A visszavetést egy deklarációs kifejezés (§12.20) adhatja meg az azonosítóval _; és implicit módon be van állítva (_ vagy var _) vagy explicit módon (T _). A visszavetés egy névtelen függvény paramétereként is bevezethető (12.22.2. §).
Megjegyzés:
_a deklarációk számos formájában érvényes azonosító. végjegyzet
Mivel egy elvetésnek nincs neve, az egyetlen hivatkozás az általa képviselt változóra az azt tartalmazó kifejezés.
Megjegyzés: Az elvetés azonban átadható kimeneti argumentumként, így a megfelelő kimeneti paraméter a társított tárolási helyet jelöli. végjegyzet
A rendszer először nem rendel hozzá elvetést, ezért az érték elérése mindig hiba.
Példa:
_ = "Hello".Length; (int, int, int) M(out int i1, out int i2, out int i3) { ... } (int _, var _, _) = M(out int _, out var _, out _);A példa feltételezi, hogy nincs deklaráció a névről
_a hatókörben.A hozzárendelés
_egy egyszerű mintát jelenít meg egy kifejezés eredményének figyelmen kívül hagyásához. A hívásMmegjeleníti az elvetések különböző formáit, amely elérhető a halmazokban és a kimeneti paraméterekben.záró példa
9.3 Alapértelmezett értékek
A változók következő kategóriái automatikusan inicializálódnak az alapértelmezett értékükre:
- Statikus változók.
- Osztálypéldányok példányváltozói.
- Tömbelemek.
A változó alapértelmezett értéke a változó típusától függ, és a következőképpen van meghatározva:
- Egy value_type változó esetében az alapértelmezett érték megegyezik a value_type alapértelmezett konstruktorával kiszámított értékkel (8.3.3. §).
- Egy reference_type változó esetében az alapértelmezett érték a .
null
Megjegyzés: Az alapértelmezett értékekre való inicializálás általában úgy történik, hogy a memóriakezelő vagy a szemétgyűjtő inicializálja a memóriát az all-bit-zero értékre, mielőtt használathoz rendeli. Ezért célszerű az all-bits-zero használatával a nullhivatkozást jelölni. végjegyzet
9.4 Határozott hozzárendelés
9.4.1 Általános
A függvénytagok vagy névtelen függvények végrehajtható kódjának adott helyén a rendszer azt mondja, hogy egy változót biztosan hozzárendelni, ha egy fordító egy adott statikus folyamatelemzéssel (§9.4.4) bizonyítani tudja, hogy a változó automatikusan inicializálva lett, vagy legalább egy hozzárendelés célja volt.
Megjegyzés: Informálisan kimondva, a határozott hozzárendelés szabályai a következők:
- Az eredetileg hozzárendelt változót (9.4.2. §) mindig határozottan hozzárendeltnek kell tekinteni.
- Az eredetileg nem hozzárendelt változót (9.4.3. §) egy adott helyen határozottan hozzárendeltnek kell tekinteni, ha az adott helyre vezető összes lehetséges végrehajtási útvonal legalább az alábbiak egyikét tartalmazza:
- Egy egyszerű hozzárendelés (12.24.2. §), amelyben a változó a bal operandus.
- Olyan dekonstruálási hozzárendelés (12.23.3. §), amelyben a változó a dekonstruktordeconstructor_element, beleértve a beágyazott dekonstruktorokatis.
- Olyan meghívási kifejezés (§12.8.10) vagy objektumlétrehozási kifejezés (§12.8.17.2), amely kimeneti paraméterként adja át a változót.
- Helyi változó esetén:
- a változó helyi változódeklarációja (13.6.2. §), amely tartalmazza a változó inicializálóját; Vagy
- dekonstruálási hozzárendelés (12.23.3. §), amely deklarálja a változót a destruktorban.
A fenti informális szabályok alapjául szolgáló formális specifikációt a 9.4.2., a 9.4.3. és a 9.4.4.
végjegyzet
A struct_type változók példányváltozóinak határozott hozzárendelési állapotai egyenként és együttesen is nyomon követhetők. A 9.4.2., a 9.4.3. és a 9.4.4. cikkben leírt szabályokon kívül a következő szabályok vonatkoznak struct_type változókra és azok példányváltozóira:
- A példányváltozó akkor tekinthető egyértelműen hozzárendeltnek, ha a struct_type változót tartalmazó változót határozottan hozzárendeltnek tekintik.
- A struct_type változók akkor tekinthetők egyértelműen hozzárendeltnek, ha az egyes példányváltozók egyértelműen hozzárendeltnek minősülnek.
A határozott hozzárendelés a következő környezetekben követelmény:
A változót minden olyan helyen ki kell osztani, ahol az értéket megkapják.
Megjegyzés: Ez biztosítja, hogy a nem definiált értékek soha ne fordulnak elő. végjegyzet
A változó kifejezésben való előfordulását úgy kell tekinteni, hogy a változó értékét szerzi be, kivéve, ha:
- a változó egy egyszerű feladat bal operandusa,
- a változó a dekonstruálási hozzárendelés bal operandusának része,
- a változó kimeneti paraméterként van átadva, vagy
- a változó egy struct_type változó, és egy taghozzáférés bal operandusaként fordul elő.
Minden olyan helyen, ahol referenciaparaméterként továbbítják, mindenképpen ki kell osztani egy változót.
Megjegyzés: Ez biztosítja, hogy a meghívandó függvénytag figyelembe vegye az eredetileg hozzárendelt referenciaparamétert. végjegyzet
Minden olyan helyen, ahol bemeneti paraméterként továbbítják, mindenképpen ki kell osztani egy változót.
Megjegyzés: Ez biztosítja, hogy a meghívandó függvénytag figyelembe vegye az eredetileg hozzárendelt bemeneti paramétert. végjegyzet
A függvénytag összes kimeneti paraméterét minden olyan helyen ki kell osztani, ahol a függvénytag visszatér (egy visszatérési utasítással vagy a függvénytag törzsének végéig elért végrehajtással).
Megjegyzés: Ez biztosítja, hogy a függvénytagok ne adjanak vissza nem definiált értékeket a kimeneti paraméterekben, így lehetővé teszi a fordító számára, hogy olyan függvénytag-meghívást vegyenek figyelembe, amely egy változót a változóhoz való hozzárendeléssel egyenértékű kimeneti paraméterként vesz fel. végjegyzet
A
thisstruct_type példánykonstruktor változóját minden olyan helyen ki kell osztani, ahol a példánykonstruktor visszatér.
9.4.2 Eredetileg hozzárendelt változók
A változók következő kategóriái először hozzárendeltként vannak besorolva:
- Statikus változók.
- Osztálypéldányok példányváltozói.
- Az eredetileg hozzárendelt szerkezetváltozók példányváltozói.
- Tömbelemek.
- Értékparaméterek.
- Referenciaparaméterek.
- Bemeneti paraméterek.
- Záradékban vagy
catchutasításbanforeachdeklarált változók.
9.4.3 Kezdetben nem hozzárendelt változók
A változók alábbi kategóriái kezdetben nem hozzárendeltként vannak besorolva:
- Az eredetileg nem hozzárendelt strukturált változók példányváltozói.
- Kimeneti paraméterek, beleértve a
thisszerkezetpéldány-konstruktorok konstruktor-inicializáló nélküli változóját. - Helyi változók, kivéve a záradékban vagy
catchutasításbanforeachdeklaráltakat.
9.4.4 A határozott hozzárendelés meghatározásának pontos szabályai
9.4.4.1 Általános
Annak megállapításához, hogy az egyes használt változók egyértelműen hozzárendelve vannak-e, a fordítónak olyan folyamatot kell használnia, amely megegyezik az ebben az alklámban leírt eljárással.
A függvénytag törzse deklarálhat egy vagy több kezdetben nem hozzárendelt változót. Minden eredetileg nem hozzárendelt vváltozóra vonatkozóan a fordítónak a függvénytag alábbi pontjain meg kell határoznia a vvégleges hozzárendelési állapotot.
- Az egyes utasítások elején
- Minden utasítás végén (13.2. §)
- Minden olyan íven, amely a vezérlést egy másik utasításba vagy egy utasítás végpontjára továbbítja
- Az egyes kifejezések elején
- Az egyes kifejezések végén
A v végleges hozzárendelési állapota a következő lehet:
- Határozottan hozzárendelve. Ez azt jelzi, hogy az ehhez a ponthoz tartozó összes lehetséges vezérlőfolyamaton a v érték van hozzárendelve.
- Nem biztos, hogy hozzárendelték. Egy változónak egy típuskifejezés
boolvégén lévő állapota esetén a nem feltétlenül hozzárendelt változó állapota az alábbi alállapotok egyikébe kerülhet (de nem feltétlenül):- A valódi kifejezés után egyértelműen hozzárendelve. Ez az állapot azt jelzi, hogy a v egyértelműen ki van rendelve, ha a logikai kifejezés igazként van kiértékelve, de nem feltétlenül van hozzárendelve, ha a logikai kifejezés hamisként van kiértékelve.
- A hamis kifejezés után egyértelműen hozzárendelve. Ez az állapot azt jelzi, hogy a v akkor van hozzárendelve, ha a logikai kifejezés hamisként van kiértékelve, de nem feltétlenül van hozzárendelve, ha a logikai kifejezés igazként van kiértékelve.
Az alábbi szabályok szabályozzák, hogy az egyes helyeken hogyan határozható meg egy v változó állapota.
9.4.4.2 Az utasítások általános szabályai
- a v nem feltétlenül van hozzárendelve egy függvénytag törzsének elején.
- A v végleges hozzárendelési állapotát bármely más utasítás elején a v végleges hozzárendelési állapotának ellenőrzésével határozzuk meg az összes olyan vezérlőfolyamat-átvitelen, amely az adott utasítás kezdetét célozza. Ha (és csak akkor), ha a v minden ilyen vezérlési folyamat átviteléhez biztosan hozzá van rendelve, akkor a v az utasítás elején van hozzárendelve. A lehetséges vezérlőfolyamat-átvitelek halmaza ugyanúgy van meghatározva, mint az ellenőrzőutasítások elérhetősége (13.2. §).
- A v végleges hozzárendelési állapotát az a , , ,
blockcheckeduncheckedifwhiledoforforeachvagylockutasítás végpontjánusinghatározza meg, ha ellenőrzi a vswitchállapotát az összes olyan vezérlőfolyamat-átvitelen, amely az adott utasítás végpontját célozza. Ha a v minden ilyen vezérlőfolyamat-átvitelhez hozzá van rendelve, akkor a v egyértelműen az utasítás végén van hozzárendelve. Ellenkező esetben a v nincs egyértelműen hozzárendelve az utasítás végén. A lehetséges vezérlőfolyamat-átvitelek halmaza ugyanúgy van meghatározva, mint az ellenőrzőutasítások elérhetősége (13.2. §).
Megjegyzés: Mivel egy nem elérhető utasításhoz nincsenek vezérlőútvonalak, a v minden bizonnyal a nem elérhető utasítások elején van hozzárendelve. végjegyzet
9.4.4.3 Utasítások blokkolása, ellenőrzött és nem ellenőrzött utasítások
A blokkban lévő utasításlista első utasítására (vagy ha az utasításlista üres, akkor a blokk végpontjára, ha az utasításlista üres) a vezérlőelemen lévő v végleges hozzárendelési állapota megegyezik a blokk előtti v végleges hozzárendelési állapotával, checkedvagy unchecked az utasítással.
9.4.4.4 Kifejezési utasítások
Kifejezési utasítás stmt értéke, amely az expr kifejezésből áll:
- a v a kitevő elején ugyanazzal a határozott hozzárendelési állapottal rendelkezik, mint az stmt elején.
- Ha a v az expr végén van hozzárendelve, akkor az az stmt végpontján van hozzárendelve; ellenkező esetben nincs egyértelműen hozzárendelve az stmt végpontján.
9.4.4.5 Nyilatkozatok
- Ha az stmt inicializálók nélküli deklarációs utasítás, akkor a v az stmt végpontján ugyanazzal a határozott hozzárendelési állapottal rendelkezik, mint az stmt elején.
- Ha az stmt inicializálókkal rendelkező deklarációs utasítás, akkor a v végleges hozzárendelési állapota úgy lesz meghatározva, mintha az stmt utasításlista volna, és mindegyik deklarációhoz egy hozzárendelési utasítás tartozik egy inicializálóval (a deklaráció sorrendjében).
9.4.4.6 Ha utasítás
Az űrlap utasítása:
if ( «expr» ) «then_stmt» else «else_stmt»
- a v a kitevő elején ugyanazzal a határozott hozzárendelési állapottal rendelkezik, mint az stmt elején.
- Ha a v az expr végén van hozzárendelve, akkor a vezérlési folyamat átviteléhez egyértelműen hozzá van rendelve a then_stmt és a else_stmt vagy az stmt végponthoz, ha nincs más záradék.
- Ha a v állapot az expr végén "határozottan igaz kifejezés után" állapottal rendelkezik, akkor az biztosan hozzá van rendelve a vezérlőfolyamat-átvitelhez then_stmt, és nem feltétlenül van hozzárendelve a vezérlőfolyamat-átvitelhez sem else_stmt, sem az stmt végponthoz, ha nincs más záradék.
- Ha a v állapot "határozottan hozzárendelve van hamis kifejezés után" az expr végén, akkor az biztosan hozzá van rendelve a vezérlőfolyamat-átvitelhez else_stmt, és nem feltétlenül van hozzárendelve a vezérlőfolyamat-átvitelhez then_stmt. Mindenképpen az stmt végpontján van hozzárendelve, ha és csak akkor, ha határozottan a then_stmt végpontján van hozzárendelve.
- Ellenkező esetben a v nem feltétlenül van hozzárendelve a vezérlési folyamat átviteléhez sem a then_stmt, sem a else_stmt, sem az stmt végponthoz, ha nincs más záradék.
9.4.4.7 Kapcsoló utasítások
switch Egy vezérlőkifejezést tartalmazó stmt utasítás esetén:
A v végleges hozzárendelési állapota az expr elején ugyanaz, mint a v állapota az stmt elején.
A v végleges hozzárendelési állapota az eset őrzési záradékának elején a következő:
- Ha v a switch_label deklarált mintaváltozó: "határozottan hozzárendelve".
- Ha a védő záradékot tartalmazó kapcsolócímke (13.8.3. §) nem érhető el: "határozottan hozzárendelve".
- Ellenkező esetben a v állapota megegyezik az expr utáni v állapotával.
példa: A második szabály szükségtelenné teszi, hogy egy fordító hibát adjon ki, ha egy nem hozzárendelt változó elérhetetlen kódban érhető el. A b állapota "határozottan hozzárendelve" van a nem elérhető kapcsoló címkéjében
case 2 when b.bool b; switch (1) { case 2 when b: // b is definitely assigned here. break; }záró példa
A vezérlőfolyamat egy elérhető kapcsolóblokk-utasításlistára való átvitelének v végleges hozzárendelési állapota a következő:
- Ha a vezérlőátvitel egy "goto-eset" vagy "goto default" utasítás miatt történt, akkor a v állapota megegyezik a "goto" utasítás elején lévő állapottal.
- Ha a vezérlőátvitel a
defaultkapcsoló címkéje miatt történt, akkor a v állapota megegyezik az expr utáni v állapottal. - Ha a vezérlőátvitel egy elérhetetlen kapcsolócímke miatt történt, akkor a v állapota "határozottan hozzárendelve" lesz.
- Ha a vezérlőátvitelt egy elérhető kapcsolócímke okozta egy védő záradékkal, akkor a v állapota megegyezik az őrzáradék utáni v állapottal.
- Ha a vezérlőátvitel egy védő záradék nélküli, elérhető kapcsolócímke miatt történt, akkor a v állapota
- Ha v a switch_label deklarált mintaváltozó: "határozottan hozzárendelve".
- Ellenkező esetben a v állapota megegyezik az expr utáni v állapotával.
Ezeknek a szabályoknak az a következménye, hogy egy switch_label deklarált mintaváltozó a kapcsolószakasz utasításaiban "nem feltétlenül lesz hozzárendelve", ha nem ez az egyetlen elérhető kapcsolócímke a szakaszában.
Példa:
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; … } }záró példa
9.4.4.8 Utasítások
Az űrlap utasítása:
while ( «expr» ) «while_body»
- a v a kitevő elején ugyanazzal a határozott hozzárendelési állapottal rendelkezik, mint az stmt elején.
- Ha a v az expr végén van hozzárendelve, akkor a vezérlőfolyamat-átvitelhez egyértelműen hozzá van rendelve a while_body és az stmt végpontja felé.
- Ha v az expr végén a "határozottan hozzárendelt igaz kifejezés után" állapottal rendelkezik, akkor az biztosan hozzá van rendelve a vezérlőfolyamat-átvitelhez while_body, de az stmt végpontján nem.
- Ha v az expr végén a "határozottan hozzárendelt hamis kifejezés után" állapottal rendelkezik, akkor a vezérlőfolyamat-átvitelhez egyértelműen hozzá van rendelve az stmt végpontjára, de nem feltétlenül van hozzárendelve a vezérlőfolyamat-átvitelhez while_body.
9.4.4.9 Do utasítás
Az űrlap utasítása:
do «do_body» while ( «expr» ) ;
- a v ugyanazzal a határozott hozzárendelési állapottal rendelkezik, mint az stmt elejétől a do_body, mint az stmt elején.
- a v az expr elején ugyanazzal a határozott hozzárendelési állapottal rendelkezik, mint a do_body végpontján.
- Ha a v az expr végén van hozzárendelve, akkor az egyértelműen az stmt végpontjára történő vezérlési folyamat átviteléhez van hozzárendelve.
- Ha a v állapot "határozottan hozzárendelve van hamis kifejezés után" az expr végén, akkor az biztosan hozzá van rendelve a vezérlőfolyamat-átvitelhez az stmt végpontjára, de nem feltétlenül van hozzárendelve a vezérlőfolyamat-átvitelhez do_body.
9.4.4.10 Utasítások esetén
Az űrlap egy nyilatkozatához:
for ( «for_initializer» ; «for_condition» ; «for_iterator» )
«embedded_statement»
a határozott hozzárendelés ellenőrzése úgy történik, mintha az utasítás meg lett volna írva:
{
«for_initializer» ;
while ( «for_condition» )
{
«embedded_statement» ;
LLoop: «for_iterator» ;
}
}
olyan utasításokkal, continue amelyek a for lefordított utasítást a címkét gotomegcélzó utasításokra LLoop irányulnak. Ha a for_condition nincs megadva az utasításból, akkor a for végleges hozzárendelés kiértékelése úgy folytatódik, mintha for_condition a fenti bővítés során igaz értékre cserélték volna.
9.4.4.11 Törés, folytatás és goto utasítások
A v végleges hozzárendelési állapota az , breakvagy continue utasítás által gotookozott vezérlőfolyamat-átvitelen ugyanaz, mint a v végleges hozzárendelési állapota az utasítás elején.
9.4.4.12 Dobás utasítások
Az űrlap utasítása:
throw «expr» ;
a v végleges hozzárendelési állapota az expr elején ugyanaz, mint a v végleges hozzárendelési állapota az stmt elején.
9.4.4.13 Visszatérési utasítások
Az űrlap utasítása:
return «expr» ;
- A v végleges hozzárendelési állapota az expr elején ugyanaz, mint a v végleges hozzárendelési állapota az stmt elején.
- Ha v egy kimeneti paraméter, akkor a következőhöz kell hozzárendelni:
- az expr után
- vagy az utasítást tartalmazó
finallyblokktry-finallytry-catch-finallyvégén.return
Az űrlap utasítása:
return ;
- Ha v egy kimeneti paraméter, akkor a következőhöz kell hozzárendelni:
- stmt előtt
- vagy az utasítást tartalmazó
finallyblokktry-finallytry-catch-finallyvégén.return
9.4.4.14 Próbálkozási utasítások
Az űrlap utasítása:
try «try_block»
catch ( ... ) «catch_block_1»
...
catch ( ... ) «catch_block_n»
- A v végleges hozzárendelési állapota a try_block elején ugyanaz, mint a v végleges hozzárendelési állapota az stmt elején.
- A v végleges hozzárendelési állapota a catch_block_i elején (bármely i esetén) megegyezik az stmt elején lévő v végleges hozzárendelési állapotával.
- Az stmt végpontján lévő v végleges hozzárendelési állapota akkor van egyértelműen hozzárendelve, ha (és csak akkor) v van hozzárendelve a try_block végpontján és minden catch_block_i (minden i esetében 1-től n-ig).
9.4.4.15 Próba-végi utasítások
Az űrlap utasítása:
try «try_block» finally «finally_block»
- A v végleges hozzárendelési állapota a try_block elején ugyanaz, mint a v végleges hozzárendelési állapota az stmt elején.
- A v végleges hozzárendelési állapota a finally_block elején ugyanaz, mint a v végleges hozzárendelési állapota az stmt elején.
- Az stmt végpontján lévő v végleges hozzárendelési állapota akkor van egyértelműen hozzárendelve, ha (és csak akkor), ha az alábbiak közül legalább az egyik igaz:
- a v egyértelműen a try_block végpontján van hozzárendelve
- a v egyértelműen a finally_block végpontján van hozzárendelve
Ha olyan vezérlőfolyamat-átvitel (például goto utasítás) történik, amely try_block belül kezdődik, és try_block kívül végződik, akkor a v is határozottan hozzárendeltnek minősül az adott vezérlőfolyamat-átvitelhez, ha a v egyértelműen a finally_block végpontján van hozzárendelve. (Ez nem csak akkor igaz, ha – ha a v-t más okból rendelik hozzá ehhez a vezérlőfolyamat-átvitelhez, akkor továbbra is határozottan hozzárendeltnek tekintik.)
9.4.4.16 Try-catch-finally utasítások
Az űrlap egy nyilatkozatához:
try «try_block»
catch ( ... ) «catch_block_1»
...
catch ( ... ) «catch_block_n»
finally «finally_block»
a határozott hozzárendelés elemzése úgy történik, mintha az utasítás egy try-finally utasítást tartalmazó try-catch utasítás volna:
try
{
try «try_block»
catch ( ... ) «catch_block_1»
...
catch ( ... ) «catch_block_n»
}
finally «finally_block»
Példa: Az alábbi példa bemutatja, hogy egy
tryutasítás különböző blokkjai (13.11. §) hogyan befolyásolják a határozott hozzárendelést.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 } }záró példa
9.4.4.17 Foreach-utasítások
Az űrlap utasítása:
foreach ( «type» «identifier» in «expr» ) «embedded_statement»
- A v végleges hozzárendelési állapota az expr elején ugyanaz, mint a v állapota az stmt elején.
- Az embedded_statement vagy az stmt végpontjára történővezérlési folyamat v végleges hozzárendelési állapota megegyezik az expr végén lévő v állapottal.
9.4.4.18 Utasítások használata
Az űrlap utasítása:
using ( «resource_acquisition» ) «embedded_statement»
- A v végleges hozzárendelési állapota a resource_acquisition elején ugyanaz, mint a v állapota az stmt elején.
- A vezérlési folyamat embedded_statement-ra történő átvitelének v végleges hozzárendelési állapota megegyezik a resource_acquisition végén lévő v állapottal.
9.4.4.19 Zárolási utasítások
Az űrlap utasítása:
lock ( «expr» ) «embedded_statement»
- A v végleges hozzárendelési állapota az expr elején ugyanaz, mint a v állapota az stmt elején.
- A vezérlési folyamat embedded_statement felé történő átvitelének v végleges hozzárendelési állapota megegyezik az expr végén lévő v állapottal.
9.4.4.20 Hozamkimutatások
Az űrlap utasítása:
yield return «expr» ;
- A v végleges hozzárendelési állapota az expr elején ugyanaz, mint a v állapota az stmt elején.
- Az stmt végén lévő v végleges hozzárendelési állapota megegyezik az expr végén lévő v állapottal.
Az yield break utasításnak nincs hatása a határozott hozzárendelés állapotára.
9.4.4.21 Az állandó kifejezések általános szabályai
Az alábbiak minden állandó kifejezésre vonatkoznak, és elsőbbséget élveznek az alábbi alklámok szabályaival szemben, amelyek alkalmazhatók:
Állandó értékű truekifejezés esetén:
- Ha a v határozottan a kifejezés előtt van hozzárendelve, akkor a v egyértelműen a kifejezés után lesz hozzárendelve.
- Ellenkező esetben a v a kifejezés után "határozottan hamis kifejezés után van hozzárendelve".
Példa:
int x; if (true) {} else { Console.WriteLine(x); }záró példa
Állandó értékű falsekifejezés esetén:
- Ha a v határozottan a kifejezés előtt van hozzárendelve, akkor a v egyértelműen a kifejezés után lesz hozzárendelve.
- Ellenkező esetben a v a kifejezés után "határozottan igaz kifejezés után van hozzárendelve".
Példa:
int x; if (false) { Console.WriteLine(x); }záró példa
Az összes többi állandó kifejezés esetében a v végleges hozzárendelési állapota a kifejezés után ugyanaz, mint a v végleges hozzárendelési állapota a kifejezés előtt.
9.4.4.22 Egyszerű kifejezések általános szabályai
A következő szabály az ilyen típusú kifejezésekre vonatkozik: literálok (12.8.2.§), egyszerű nevek (12.8.4.§), taghozzáférés-kifejezések (12.8.7.§), nem indexelt alapelérési kifejezések (12.§.). 8.15), typeof kifejezések (12.8.18.§), alapértelmezett értékkifejezések (12.8.21.§), nameof kifejezések (12.8.23. §) és deklarációs kifejezések (12.20. §).
- Az ilyen kifejezés végén lévő v végleges hozzárendelési állapota megegyezik a kifejezés elején lévő v végleges hozzárendelési állapotával.
9.4.4.23 A beágyazott kifejezéseket tartalmazó kifejezések általános szabályai
Az ilyen típusú kifejezésekre a következő szabályok vonatkoznak: zárójeles kifejezések (12.8.5.§), rekordkifejezések (12.8.6.§), elemhozzáférési kifejezések (12.8.12.§), indexeléssel rendelkező alapelérési kifejezések (12.8.15.§), növekményes és csökkenő kifejezések (12.8.16. §, §12.9.7), öntött kifejezések (12.9.8. §), unáris +, -, , ~*kifejezések, bináris +, -, *, /, , %<<>><<=>>=, ==, !=, isas, &, |kifejezések ^ (§12.13, §12.14, §12.15, §12.16), összetett hozzárendelési kifejezések (12.24.5. §) checked és unchecked kifejezések (12.8.20. §), tömb- és delegáltlétrehozási kifejezések (12.8.17. §) és await kifejezések (12.9.9. §).
Mindegyik kifejezés egy vagy több olyan alkifejezéssel rendelkezik, amelyeket feltétel nélkül, rögzített sorrendben értékelnek ki.
Példa: A bináris
%operátor kiértékeli az operátor bal oldalát, majd a jobb oldalt. Az indexelési művelet kiértékeli az indexelt kifejezést, majd kiértékeli az egyes indexkifejezéseket balról jobbra haladva. záró példa
Az expr kifejezéshez, amelynek kibontása ki van osztva₁, expr₂, ..., exprₓ, az adott sorrendben kiértékelve:
- A v végleges hozzárendelési állapota az expr₁ elején ugyanaz, mint a végleges hozzárendelési állapot az expr elején.
- A kiutasítás elején lévő v végleges hozzárendelési állapota (i nagyobb, mint egy) megegyezik a kitérés végén lévő végleges hozzárendelési állapottal₋ ₁.
- Az expr végén lévő v végleges hozzárendelési állapota megegyezik az exprₓ végén található határozott hozzárendelési állapottal.
9.4.4.24 Meghívási kifejezések és objektumlétrehozási kifejezések
Ha a meghívandó metódus részleges metódus, amely nem implementál részleges metódusdeklarációt, vagy feltételes metódus vagy feltételes helyi függvény, amelynek a hívását kihagyja (§23.5.3.2, §conditional-local-function), akkor a meghívás utáni v végleges hozzárendelési állapota megegyezik a meghívás előtti v végleges hozzárendelési állapotával. Ellenkező esetben a következő szabályok érvényesek:
Az űrlap meghívási kifejezésének kifejezése :
«primary_expression» ( «arg₁», «arg₂», … , «argₓ» )
vagy az űrlap objektumlétrehozó kifejezésének kifejezése :
new «type» ( «arg₁», «arg₂», … , «argₓ» )
- Invokációs kifejezés esetén a v végleges hozzárendelési állapota primary_expression előtt megegyezik az expr előtti v állapottal.
- Invokációs kifejezés esetén az arg₁ előtti v végleges hozzárendelési állapota megegyezik az primary_expression utáni v állapotával.
- Objektumlétrehozási kifejezés esetén a v végleges hozzárendelési állapota az arg₁ előtt megegyezik a kiff előtti v állapottal.
- Minden argi argumentum esetében az argi utáni v végleges hozzárendelési állapotát a normál kifejezési szabályok határozzák meg, figyelmen kívül hagyva az esetleges
in,outvagyrefmódosítókat. - Az egyes argumentumok argi minden i nagyobb, az argi előtti v végleges hozzárendelési állapota megegyezik az argi₋₁ utáni v állapotával.
- Ha a v változó argumentumként van átadva (azaz a "out
out" alak argumentuma) az argumentumok bármelyikében, akkor a kiutasítás utáni v állapot biztosan ki lesz rendelve. Ellenkező esetben az expr utáni v állapota megegyezik az argₓ utáni v állapotával. - Tömb inicializálók (12.8.17.5.§), objektum-inicializálók (§12.8.17.3.3.1. §), gyűjtemény inicializálók (§12.8.17.3.1) és névtelen objektum-inicializálók (12.8.17.4. §) esetén a végleges hozzárendelés állapotát az határozza meg, hogy ezek a szerkezetek a definíciójuk szerint vannak meghatározva.
9.4.4.25 Egyszerű és dekonstruáló hozzárendelési kifejezések
Az e kifejezésben a hozzárendelési célok készletét a következőképpen kell definiálni:
- Ha az e egy dekonstruktor, akkor az e-beli hozzárendelési célok az e elemek hozzárendelési céljainak egyesítését képezik.
- Ellenkező esetben a hozzárendelési célértékek e.
Az űrlap kifejezésének kifejezése :
«expr_lhs» = «expr_rhs»
- A v végleges hozzárendelési állapota expr_lhs előtt ugyanaz, mint a v végleges hozzárendelésiállapota az expr előtt.
- A v végleges hozzárendelési állapota expr_rhs előtt ugyanaz, mint a v végleges hozzárendelési állapota expr_lhs után.
- Ha a v a expr_lhs hozzárendelési célja, akkor az expr után a v végleges hozzárendelési állapota biztosan ki lesz rendelve. Ellenkező esetben, ha a hozzárendelés egy szerkezettípus példánykonstruktorán belül történik, és a V egy automatikusan implementált P tulajdonság rejtett háttérmezője a létrehozandó példányon, és a P tulajdonsághozzáférés a expr_lhs hozzárendelési célja, akkor a kiutasítás utáni v végleges hozzárendelési állapota biztosan ki van rendelve. Ellenkező esetben a kiutasítás utáni v végleges hozzárendelési állapota megegyezik a v végleges hozzárendelésiállapota expr_rhs után.
Példa: Az alábbi kódban
class A { static void F(int[] arr) { int x; arr[x = 1] = x; // ok } }a változót
xa második egyszerű hozzárendelés bal oldali elemének kiértékelése utánarr[x = 1]határozottan hozzárendeltnek tekintjük.záró példa
9.4.4.26 > kifejezések
Az űrlap kifejezésének kifejezése :
«expr_first» && «expr_second»
- A v végleges hozzárendelési állapota expr_first előtt ugyanaz, mint a v végleges hozzárendelésiállapota az expr előtt.
- Az expr_second előtti v végleges hozzárendelésiállapota akkor és csak akkor van hozzárendelve, ha a expr_first utáni v állapota egyértelműen ki van rendelve, vagy "a valódi kifejezés után határozottan hozzárendelve". Ellenkező esetben nincs egyértelműen hozzárendelve.
- A kiutasítás utáni v végleges hozzárendelési állapotát a következő határozza meg:
- Ha az expr_first után a v állapota egyértelműen ki van rendelve, akkor az expr után a v állapota biztosan ki van rendelve.
- Ellenkező esetben, ha az expr_second utáni v állapota egyértelműen hozzárendelve van, és a expr_first utáni v állapota "határozottan a hamis kifejezés után van hozzárendelve", akkor az expr után a v állapota egyértelműen ki van rendelve.
- Ellenkező esetben, ha az expr_second utáni v állapota egyértelműen ki van rendelve, vagy "az igaz kifejezés után határozottan ki van rendelve", akkor az expr utáni v állapota "a valódi kifejezés után határozottan hozzárendelve" lesz.
- Ellenkező esetben, ha a expr_first utáni v állapota "hamis kifejezés után határozottan hozzárendelve", és a expr_second utáni v állapota "határozottan a hamis kifejezés után van hozzárendelve", akkor az expr utáni v állapot "határozottan a hamis kifejezés után van hozzárendelve".
- Ellenkező esetben a kiutasítás utáni v állapot nincs hozzárendelve.
Példa: Az alábbi kódban
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 } }a változót
iegyértelműen hozzárendeltnek tekintjük egyifutasítás egyik beágyazott utasításában, a másikban azonban nem.ifA metódusFutasításában a változótimindenképpen az első beágyazott utasításhoz rendeli hozzá, mert a kifejezés(i = y)végrehajtása mindig megelőzi ennek a beágyazott utasításnak a végrehajtását. Ezzel szemben a változóinem feltétlenül van hozzárendelve a második beágyazott utasításhoz, mivelx >= 0előfordulhat, hogy hamis tesztet végzett, ami azt eredményezi, hogy a változóinincs hozzárendelve.záró példa
9.4.4.27 || Kifejezések
Az űrlap kifejezésének kifejezése :
«expr_first» || «expr_second»
- A v végleges hozzárendelési állapota expr_first előtt ugyanaz, mint a v végleges hozzárendelésiállapota az expr előtt.
- Az expr_secondelőtti v végleges hozzárendelési állapota akkor és csak akkor van hozzárendelve, ha az expr_first utáni v állapota vagy "a hamis kifejezés után egyértelműen hozzárendelve". Ellenkező esetben nincs egyértelműen hozzárendelve.
- A kiutasítás utáni v végleges hozzárendelési állapotát a következő határozza meg:
- Ha az expr_first után a v állapota egyértelműen ki van rendelve, akkor az expr után a v állapota biztosan ki van rendelve.
- Ellenkező esetben, ha az expr_second utáni v állapota egyértelműen hozzárendelve van, és a expr_first utáni v állapota "határozottan igaz kifejezés után van hozzárendelve", akkor az expr után a v állapota biztosan ki van rendelve.
- Ellenkező esetben, ha a expr_second utáni v állapota egyértelműen hozzárendelve van, vagy "határozottan a hamis kifejezés után van hozzárendelve", akkor az expr utáni v állapota "a hamis kifejezés után egyértelműen hozzárendelve".
- Ellenkező esetben, ha a expr_first utáni v állapota "a valódi kifejezés után egyértelműen van hozzárendelve", és a expr_second utáni v állapota "az igaz kifejezés után egyértelműen hozzárendelve", akkor a kiff utáni v állapot "a valódi kifejezés után határozottan hozzárendelve" lesz.
- Ellenkező esetben a kiutasítás utáni v állapot nincs hozzárendelve.
Példa: Az alábbi kódban
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 } }a változót
iegyértelműen hozzárendeltnek tekintjük egyifutasítás egyik beágyazott utasításában, a másikban azonban nem.ifA metódusGutasításában a változótia második beágyazott utasításban rendeli hozzá, mert a kifejezés(i = y)végrehajtása mindig megelőzi ennek a beágyazott utasításnak a végrehajtását. Ezzel szemben a változóinem feltétlenül van hozzárendelve az első beágyazott utasításhoz, mivelx >= 0lehet, hogy igaz lett volna tesztelve, ami azt eredményezi, hogy a változóinincs hozzárendelve.záró példa
9.4.4.28 ! Kifejezések
Az űrlap kifejezésének kifejezése :
! «expr_operand»
- A v végleges hozzárendelési állapota expr_operand előtt ugyanaz, mint a v végleges hozzárendelésiállapota az expr előtt.
- A kiutasítás utáni v végleges hozzárendelési állapotát a következő határozza meg:
- Ha az expr_operand utáni állapotot
vegyértelműen hozzárendeli, akkor a kitevő utáni állapototvhatározottan hozzárendeli. - Ellenkező esetben, ha az expr_operand
vállapot "hamis kifejezés után egyértelműen van hozzárendelve", akkor az exprvállapot "a valódi kifejezés után határozottan hozzárendelve" lesz. - Ellenkező esetben, ha a expr_operand
vállapot "a valódi kifejezés után egyértelműen van hozzárendelve", akkor az expr utáni v állapot "a hamis kifejezés után egyértelműen hozzárendelve". - Ellenkező esetben a kiutasítás
vállapot nincs egyértelműen hozzárendelve.
- Ha az expr_operand utáni állapotot
9.4.4.29 ?? Kifejezések
Az űrlap kifejezésének kifejezése :
«expr_first» ?? «expr_second»
- A v végleges hozzárendelési állapota expr_first előtt ugyanaz, mint a v végleges hozzárendelésiállapota az expr előtt.
- A v végleges hozzárendelési állapota expr_second előtt ugyanaz, mint a v végleges hozzárendelési állapota expr_first után.
- A kiutasítás utáni v végleges hozzárendelési utasítását a következő határozza meg:
- Ha expr_first állandó kifejezés (12.26.§),
nullakkor a kifés utáni v állapota megegyezik a expr_second utáni állapottal. - Ha expr_first közvetlenül tartalmaz (§12.1) egy null-feltételes kifejezést E, és v határozottan hozzárendelt után nem feltételes megfelelője E₀ (§9.4.4.35), akkor a végleges hozzárendelés állapota vután expr ugyanaz, mint a végleges hozzárendelés állapota v után expr_second.
- Ellenkező esetben a kiutasítás utáni v állapota megegyezik a v végleges hozzárendelési állapota expr_first után.
- Ha expr_first állandó kifejezés (12.26.§),
Megjegyzés: A fenti szabály formalizálja, hogy egy olyan kifejezés esetében, mint
a?.M(out x) ?? (x = false)például aa?.M(out x)teljes kiértékelés és a nem null érték előállítása, amely esetbenxki lett rendelve, vagy a kiértékelt, ebben azx = falseesetbenxszintén ki lett rendelve. Ezértxa kifejezés után mindig hozzá lesz rendelve.Ez a forgatókönyvet is kezeli, ha megfigyeli, hogy a
dict?.TryGetValue(key, out var value) ?? falsev egyértelműen a következő utándict.TryGetValue(key, out var value)van hozzárendelve, a v pedig "határozottan ki van rendelve, ha igaz" utánfalse, és megállapítja, hogy a v-t "határozottan ki kell osztani, ha igaz".Az általánosabb megfogalmazás néhány szokatlanabb forgatókönyv kezelését is lehetővé teszi, például:
if (x?.M(out y) ?? (b && z.M(out y))) y.ToString();if (x?.M(out y) ?? z?.M(out y) ?? false) y.ToString();végjegyzet
9.4.4.30 ?: kifejezések
Az űrlap kifejezésének kifejezése :
«expr_cond» ? «expr_true» : «expr_false»
- A v végleges hozzárendelési állapota expr_cond előtt megegyezik a kiff előtti v állapottal.
- Az expr_true előtti v végleges hozzárendelésiállapota akkor lesz egyértelműen hozzárendelve, ha a expr_cond utáni v állapota egyértelműen ki van rendelve, vagy "a valódi kifejezés után határozottan hozzárendelve".
- A v végleges hozzárendelési állapota expr_false előtt, ha az expr_cond utáni v állapota egyértelműen ki van rendelve, vagy "a hamis kifejezés után határozottan hozzárendelve".
- A kiutasítás utáni v végleges hozzárendelési állapotát a következő határozza meg:
- Ha expr_cond állandó kifejezés (12.26.§),
trueakkor az expr után a v állapota megegyezik a expr_true utáni állapottal. - Ellenkező esetben, ha expr_cond egy állandó kifejezés (12.26.§), akkor az
falseutáni v állapota megegyezik a expr_false utáni állapottal. - Ellenkező esetben, ha a expr_true utáni v állapota egyértelműen ki van rendelve, és az expr_false utáni v állapota egyértelműen ki van rendelve, akkor a kiff utáni v állapota biztosan ki van rendelve.
- Ellenkező esetben a kiutasítás utáni v állapot nincs hozzárendelve.
- Ha a expr_true utáni v állapot "határozottan ki van rendelve, ha igaz", és a expr_false utáni v állapota "határozottan ki van rendelve, ha igaz", akkor az expr utáni v állapota "határozottan ki van rendelve, ha igaz".
- Ha a expr_true utáni v állapota "határozottan hozzárendelve, ha hamis", és a expr_false utáni v állapota "határozottan ki van rendelve, ha hamis", akkor az expr utáni v állapota "határozottan hozzárendelve, ha hamis".
- Ha expr_cond állandó kifejezés (12.26.§),
Megjegyzés: Ha egy feltételes kifejezés mindkét karja feltételes állapotot eredményez, a rendszer a megfelelő feltételes állapotokat összekapcsolja és propagálja ahelyett, hogy ki szeretné bontani az állapotot, és lehetővé teszi a végleges állapot feltételesen nem való használatát. Ez az alábbihoz hasonló forgatókönyveket tesz lehetővé:
bool b = true; object x = null; int y; if (b ? x != null && Set(out y) : x != null && Set(out y)) { y.ToString(); } bool Set(out int x) { x = 0; return true; }végjegyzet
9.4.4.31 Névtelen függvények
Egy lambda_expression vagy anonymous_method_expression kifúvatás esetén egy törzs (blokkvagy kifejezés) törzsével:
- Egy paraméter végleges hozzárendelési állapota megegyezik egy nevesített metódus paraméterével (9.2.6. §, 9.2.7. §, 9.2.8. §).
- Egy v külső változó végleges hozzárendelési állapota a törzs előtt ugyanaz, mint a kiff előtt lévő v állapot. Vagyis a külső változók határozott hozzárendelési állapota öröklődik a névtelen függvény környezetéből.
- A külső változó v végleges hozzárendelési állapota az expr után megegyezik a kiff előtti v állapottal.
Példa: A példa
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) { ... } }fordítási idő hibát okoz, mivel a max nincs egyértelműen hozzárendelve a névtelen függvény deklarálásakor.
záró példa
Példa: A példa
class A { delegate void D(); void F() { int n; D d = () => { n = 1; }; d(); // Error, n is not definitely assigned Console.WriteLine(n); } }fordítási idő hibát is generál, mivel a névtelen függvényhez való
nhozzárendelés nincs hatással a névtelen függvényen kívüli végleges hozzárendelésinállapotra.záró példa
9.4.4.32 Dobókifejezések
Az űrlap kifejezésének kifejezése :
throw
thrown_expr
- A v végleges hozzárendelési állapota thrown_expr előtt megegyezik a kiff előtti v állapottal.
- A kiutasítás utáni v végleges hozzárendelési állapota "határozottan hozzárendelve".
9.4.4.33 A helyi függvények változóinak szabályai
A rendszer a helyi függvényeket a szülőmetódus kontextusában elemzi. A helyi függvények esetében két vezérlőfolyamat-útvonal számít: függvényhívások és delegálások.
Az egyes helyi függvények törzsének határozott hozzárendelése minden hívási helyhez külön van meghatározva. Minden egyes hívásnál a helyi függvény által rögzített változók akkor tekinthetők egyértelműen hozzárendeltnek, ha a hívás időpontjában egyértelműen hozzárendelték őket. Ezen a ponton egy vezérlőfolyamat-útvonal is létezik a helyi függvény törzséhez, és elérhetőnek tekinthető. A helyi függvény hívása után a rögzített változók, amelyek a függvénytreturn elhagyó minden vezérlőponthoz (utasítások, utasítások, yield kifejezések) lettek hozzárendelve, await a hívás helye után egyértelműen hozzárendeltnek minősülnek.
A delegált konverziók a helyi függvény törzsének vezérlőfolyamat-útvonalával rendelkeznek. A rögzített változók mindenképpen a törzshöz vannak hozzárendelve, ha azokat az átalakítás előtt egyértelműen hozzárendelték. A helyi függvény által hozzárendelt változók nem tekinthetők hozzárendeltnek az átalakítás után.
Megjegyzés: a fentiek azt jelentik, hogy a rendszer minden helyi függvényhívásnál vagy delegálásnál újra elemzi a szerveket a végleges hozzárendeléshez. A fordítóknak nem kell újra elemezniük egy helyi függvény törzsét minden egyes meghíváskor vagy delegáláskor. A megvalósításnak az adott leírásnak megfelelő eredményeket kell eredményeznie. végjegyzet
Példa: Az alábbi példa a helyi függvényekben rögzített változók határozott hozzárendelését mutatja be. Ha egy helyi függvény beolvassa a rögzített változót írás előtt, a rögzített változót mindenképpen ki kell osztani a helyi függvény meghívása előtt. A helyi függvény
F1hozzárendelés nélkül olvass. Ez egy hiba, haF1az előbb van meghívvas, és mindenképpen hozzá van rendelve.F2hozzárendelést, mielőtt elolvassai. Lehet, hogy azelőtt hívjuk meg, hogyibiztosan hozzárendelték volna. Továbbá,F3lehet meghívni utánF2, merts2határozottan hozzárendelte aF2.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); } }záró példa
9.4.4.34 is-pattern kifejezések
Az űrlap kifejezésének kifejezése :
expr_operand minta
- A v végleges hozzárendelési állapota expr_operand előtt ugyanaz, mint a v végleges hozzárendelésiállapota az expr előtt.
- Ha a "v" változó mintában van deklarálva, akkor az expr utáni "v" végleges hozzárendelési állapota "határozottan ki van rendelve, ha igaz".
- Ellenkező esetben a "v" végleges hozzárendelési állapota az expr után ugyanaz, mint a "v" végleges hozzárendelési állapota expr_operand után.
9.4.4.35 ?. Kifejezések
Az űrlap E kifejezéséhez:
«primary_expression» ?. «null_conditional_operation»
legyen az E₀ az a kifejezés, amelyet úgy kapunk, hogy szövegesen eltávolítjuk a vezetőt ? az Enull_conditional_operation egyes null_conditional_operationközül. (Az E₀ a null-feltételes kifejezés nem feltételes megfelelője .)
- A v végleges hozzárendelési állapota az E bármely pontján megegyezik az E₀ megfelelő pontján lévő végleges hozzárendelési állapottal.
- A v végleges hozzárendelési állapota az E után ugyanaz, mint a v végleges hozzárendelési állapotaprimary_expression után.
Megjegyzés: null_conditional_operation valójában nem nyelvtani szabály; hanem a nyelvhelyesség által engedélyezett bármely űrlapot jelöli. Itt a kényelem kedvéért használják. végjegyzet
Megjegyzés: A "közvetlenül tartalmaz" fogalma lehetővé teszi a viszonylag egyszerű "burkoló" kifejezések kihagyását a más értékekkel összehasonlított feltételes hozzáférések elemzésekor. Általában például a folyamat állapota várhatóan ugyanaz lesz,
((a?.b(out x))!) == trueminta?.b == truea .A szándék az, hogy lehetővé tegye az elemzés működését számos lehetséges konverzió jelenlétében egy feltételes hozzáférésen. Az "állapot, ha nem null" propagálása nem lehetséges, ha az átalakítás felhasználó által definiált, mivel a felhasználó által definiált konverziókra nem lehet számítani, hogy betartsuk azt a kényszert, hogy a kimenet csak akkor legyen null értékű, ha a bemenet nem null. Ez alól az egyetlen kivétel, ha a felhasználó által megadott konverzió bemenete nem null értékű érték. Például:
public struct S1 { } public struct S2 { public static implicit operator S2?(S1 s1) => null; }Ez magában foglalja az alábbihoz hasonló, megemelt konverziókat is:
string x; S1? s1 = null; _ = s1?.M1(x = "a") ?? s1.Value.M2(x = "a"); x.ToString(); // ok public struct S1 { public S1 M1(object obj) => this; public S2 M2(object obj) => new S2(); } public struct S2 { public static implicit operator S2(S1 s1) => default; }Ha figyelembe vesszük, hogy egy változó egy null feltételes kifejezés adott pontján van-e hozzárendelve, egyszerűen feltételezhető, hogy az ugyanazon null feltételes kifejezésen belüli előző null-feltételes műveletek sikeresek.
Feltételes kifejezés
a?.b(out x)?.c(x)esetén például a nem feltételes megfelelője .a.b(out x).c(x)Ha a korábban?.c(x)meghatározott hozzárendelésixállapotot meg kell határozni, például "hipotetikus" elemzésta.b(out x)lehet végezni, és az eredményként kapott állapot használható bemenetként.?.c(x)végjegyzet
9.4.4.36 Logikai állandó kifejezések
Az olyan kifejezéskifejtők esetében, ahol az expr egy állandó kifejezés egy bool értékkel, a függvény az expr utáni v végleges hozzárendelési állapotát határozza meg az alábbiak szerint:
- Ha az expr egy állandó kifejezés igaz értékkel, és az expr előtti v állapota "nem feltétlenül van hozzárendelve", akkor a kiff utáni v állapota "határozottan ki van rendelve, ha hamis".
- Ha az expr egy hamis értékkel rendelkező állandó kifejezés, és az expr előtti v állapot "nem feltétlenül van hozzárendelve", akkor az expr utáni v állapot "határozottan ki van rendelve, ha igaz".
Megjegyzés: Feltételezzük, hogy ha egy kifejezésnek állandó értéke van
false, akkor lehetetlen olyan ágat elérni, amely megköveteli a kifejezés visszatéréséttrue. Ezért feltételezzük, hogy a változók egyértelműen az ilyen ágakhoz vannak hozzárendelve.Ha feltételes állapotban van egy állandó kifejezés felkeresése előtt, soha nem várható el, ezért nem kell figyelembe venni az olyan forgatókönyveket, mint például a "kitérés egy állandó kifejezés igaz értékkel, és az expr előtti v állapot biztosan igaz." végjegyzet
9.4.4.37 ==/!= kifejezések
Az űrlap kifejezésének kifejezése :
«expr_first» == «expr_second»
ha == előre definiált összehasonlító operátor (12.15. §) vagy emelt operátor (12.4.8. §), a v végleges hozzárendelési állapotát a kifúrás után a következő határozza meg:
- Ha expr_first közvetlenül tartalmaz (§12.1) egy null-feltételes kifejezés E és expr_second egy állandó kifejezés értéke
null, és az állapot a v után a nem feltételes megfelelő E₀ van "határozottan hozzárendelve", akkor az állapot a kiutasítás után a "határozottan hozzárendelt, ha hamis". - Ha expr_first közvetlenül tartalmaz egy null-feltételes kifejezést E és expr_second nem null értékű kifejezés, vagy állandó kifejezés, amely nem null értékű, és a v állapota a nem feltételes megfelelő E₀ "határozottan hozzárendelve" után, akkor az expr után a v állapota "határozottan ki van rendelve, ha igaz".
- Ha expr_first típusú
bool, és expr_second egy állandó értékűtruekifejezés, akkor az expr utáni végleges hozzárendelési állapot megegyezik a expr_first utáni végleges hozzárendelési állapottal. - Ha expr_first típusú
bool, és expr_second egy állandó, értékkelfalserendelkező kifejezés, akkor az expr utáni végleges hozzárendelési állapot megegyezik a logikai negációs kifejezés!expr_first utáni v végleges hozzárendelési állapotával.
Az űrlap kifejezésének kifejezése :
«expr_first» != «expr_second»
ha != előre definiált összehasonlító operátor (12.15. §) vagy emelt operátor (12.4.8. §), a v végleges hozzárendelési állapotát a kifúrás után a következő határozza meg:
- Ha expr_first közvetlenül tartalmaz egy null-feltételes kifejezést E, és expr_second egy állandó kifejezés értékkel
null, és a v állapota után a nem feltételes megfelelő E₀ "határozottan hozzárendelt", akkor az expr utáni v állapot "határozottan hozzárendelve, ha igaz". - Ha expr_first közvetlenül tartalmaz egy null-feltételes kifejezést E és expr_second nem null értékű kifejezés, vagy nem null értékű állandó kifejezés, és a nem feltételes megfelelő E₀ után a v állapota "határozottan hozzárendelve", akkor az expr utáni v állapot "határozottan ki van rendelve, ha hamis".
- Ha expr_first típusú
bool, és expr_second egy állandó, értékkeltruerendelkező kifejezés, akkor az expr utáni végleges hozzárendelési állapot megegyezik a logikai negációs kifejezés!expr_first utáni v végleges hozzárendelési állapotával. - Ha expr_first típusú
bool, és expr_second egy állandó értékűfalsekifejezés, akkor az expr utáni végleges hozzárendelési állapot megegyezik a expr_first utáni végleges hozzárendelési állapottal.
A fenti szabályok mindegyike inmutatív.
Megjegyzés: A szabályok által kifejezett általános elképzelés a következő:
- ha a feltételes hozzáférést összehasonlítják
null, akkor a műveletek egyértelműen akkor következtek be , ha az összehasonlítás eredménye .false- ha a feltételes hozzáférést nem null értékű értéktípussal vagy nem null értékű állandóval hasonlítják össze, akkor a műveletek egyértelműen akkor következtek be, ha az összehasonlítás eredménye .
true- Mivel a felhasználó által definiált operátorok nem megbízhatók megbízható válaszokhoz az inicializálás biztonsága esetén, az új szabályok csak előre definiált
==/!=operátor használata esetén érvényesek.Ezeknek a szabályoknak a következményei a következők:
if (a?.b(out var x) == true) x() else x();hibaüzenet jelenik meg az "else" ágbanif (a?.b(out var x) == 42) x() else x();hibaüzenet jelenik meg az "else" ágbanif (a?.b(out var x) == false) x() else x();hibaüzenet jelenik meg az "else" ágbanif (a?.b(out var x) == null) x() else x();hibaüzenet jelenik meg az "then" ágbanif (a?.b(out var x) != true) x() else x();hibaüzenet jelenik meg az "then" ágbanif (a?.b(out var x) != 42) x() else x();hibaüzenet jelenik meg az "then" ágbanif (a?.b(out var x) != false) x() else x();hibaüzenet jelenik meg az "then" ágbanif (a?.b(out var x) != null) x() else x();hibaüzenet jelenik meg az "else" ágbanvégjegyzet
A 9.4.4.38 operátor és mintakifejezés
Az űrlap kifejezésének kifejezése :
«E» is «T»
ahol T bármilyen típus vagy minta:
Az E előtti v végleges hozzárendelési állapota megegyezik a v végleges hozzárendelési állapota az expr előtt.
A kiutasítás utáni v végleges hozzárendelési állapotát a következő határozza meg:
- Ha az E közvetlenül tartalmaz (§12.1) egy null-feltételes kifejezést, és az állapot v után a nem feltételes megfelelő E₀ van "határozottan hozzárendelve", és
Tminden olyan típus vagy minta, amely nem egyezik anullbemenet, akkor az állapot v után expr lesz "határozottan hozzárendelve, ha igaz." - Ha az E közvetlenül tartalmaz null-feltételes kifejezést, és a nem feltételes megfelelő E₀ utáni v állapota "határozottan hozzárendelve", és
Tegy bemenetnek megfelelőnullminta, akkor az expr utáni v állapot "határozottan hozzárendelve, ha hamis". - Ha az E típus
boolTolyan minta, amely csak egy bemenetnektruefelel meg, akkor a v végleges hozzárendelési állapota az expr után ugyanaz, mint a v végleges hozzárendelési állapotaaz E után. - Ha az E típus
boololyanTminta, amely csak egyfalsebemenetnek felel meg, akkor a v végleges hozzárendelési állapota az expr után ugyanaz, mint a v végleges hozzárendelési állapota a logikai negation kifejezés!expr után. - Ellenkező esetben, ha az E után a v végleges hozzárendelési állapota "határozottan ki van rendelve", akkor az expr után a v végleges hozzárendelési állapota "határozottan hozzárendelve" lesz.
- Ha az E közvetlenül tartalmaz (§12.1) egy null-feltételes kifejezést, és az állapot v után a nem feltételes megfelelő E₀ van "határozottan hozzárendelve", és
Megjegyzés: Ez az alklám a 9.4.4.37.-hez hasonló forgatókönyveket kezeli. Azonban nem foglalkozik rekurzív mintákkal; pl.
(a?.b(out x), c?.d(out y)) is (object, object). végjegyzet
9.5 Változóhivatkozások
A variable_reference egy változóként besorolt kifejezés . A variable_reference egy tárolóhelyet jelöl, amely az aktuális érték lekéréséhez és egy új érték tárolásához is elérhető.
variable_reference
: expression
;
Megjegyzés: A C és a C++-ban a variable_reference nevezik lvalue-nak. végjegyzet
9.6 Változóhivatkozások atomisága
A következő adattípusok olvasásának és írásának atominak kell lennie: bool, char, byte, , sbyte, shortushort, uint, intnint, , nuint, , floatés referenciatípusok. Ezenkívül az előző listában alapul szolgáló típusú enumerálási és írási műveleteknek is atominak kell lenniük. Más típusú olvasásoknak és írásoknak, beleértve longa , ulong, double, és decimal, valamint a felhasználó által meghatározott típusokat, nem kell atominak lenniük. Az erre a célra tervezett kódtárfüggvények mellett nincs garancia az atomi olvasás-módosítás-írásra, például növekmény vagy csökkenés esetén.
9.7 Referenciaváltozók és visszatérések
9.7.1 Általános
A referenciaváltozó olyan változó, amely egy másik változóra, az úgynevezett hivatkozásra hivatkozik (9.2.6. §). A referenciaváltozó a módosítóval ref deklarált helyi változó.
A referenciaváltozók egy variable_reference (9.5. §)-t tárolnak a hivatkozó számára, nem pedig a hivatkozás értékét. Ha egy referenciaváltozót használnak, ahol egy értékre van szükség, a hivatkozási értéke lesz visszaadva; Hasonlóképpen, ha egy referenciaváltozó egy hozzárendelés célja, az a hivatkozás, amelyhez hozzá van rendelve. Az a változó, amelyre a referenciaváltozó hivatkozik, azaz a hivatkozáshoz tartozó tárolt variable_reference , módosítható egy újraf-hozzárendeléssel (= ref).
Példa: Az alábbi példa egy helyi referenciaváltozót mutat be, amelynek hivatkozása egy tömb eleme:
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 } }záró példa
A hivatkozási visszatérés a visszatérési módszerből visszaadott variable_reference (15.6.1. §). Ez a variable_reference a hivatkozási visszatérés hivatkozása.
Példa: Az alábbi példa egy hivatkozási visszatérést mutat be, amelynek hivatkozása egy tömbmező eleme:
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]; } }záró példa
9.7.2 Biztonságos környezetek újrafedés
9.7.2.1 Általános
Minden referenciaváltozó betartja a biztonsági szabályokat, amelyek biztosítják, hogy a referenciaváltozó ref-safe-contextje ne legyen nagyobb, mint a hivatkozás ref-safe-contextje.
Megjegyzés: A biztonságos környezet kapcsolódó fogalma a (16.4.15.)-ben van definiálva, a kapcsolódó megkötésekkel együtt. végjegyzet
Bármely változó esetében a változó ref-safe-contextje az a környezet, amelyben az adott változóra vonatkozó variable_reference (9.5. §) érvényes. A referenciaváltozó hivatkozásának olyan ref-safe-kontextussal kell rendelkeznie, amely legalább olyan széles, mint maga a referenciaváltozó ref-safe-contextje.
Megjegyzés: A fordító a programszöveg statikus elemzésével határozza meg a ref-safe-contextt. A ref-safe-context egy változó futásidejű élettartamát tükrözi. végjegyzet
Három ref-safe-contexts van:
deklarációs blokkok: Egy helyi változóra variable_reference (§9.2.9.1) ref-safe-contextje az, hogy a helyi változó hatóköre (§13.6.2), beleértve az adott hatókörbe tartozó beágyazott beágyazott utasításis.
A helyi változóra variable_reference csak akkor érvényes hivatkozási hivatkozás egy referenciaváltozóhoz, ha a referenciaváltozó a változó ref-safe-kontextusában van deklarálva.
függvény-tag: Egy függvényen belül egy variable_reference az alábbiak bármelyikéhez ref-safe-context of function-member:
- Értékparaméterek (15.6.2.2. §) egy függvénytag-deklaráción, beleértve az osztálytagfüggvények implicit
thisértékét is; és - Egy tagfüggvény implicit hivatkozási (
ref) paramétere () a mezőkkel együtt.
A függvénytag ref-safe-context-környezetével rendelkező variable_reference csak akkor érvényes hivatkozás, ha a referenciaváltozó ugyanabban a függvénytagban van deklarálva.
- Értékparaméterek (15.6.2.2. §) egy függvénytag-deklaráción, beleértve az osztálytagfüggvények implicit
hívókörnyezet: Egy függvényen belül az alábbi variable_reference ref-safe-context hívókörnyezettel rendelkezik:
- Referenciaparaméterek (9.2.6. §) a strukturált tagfüggvény implicit
thiskivételével; - Az ilyen paraméterek tagmezői és elemei;
- Osztálytípus paramétereinek tagmezői; és
- A tömbtípus paramétereinek elemei.
- Referenciaparaméterek (9.2.6. §) a strukturált tagfüggvény implicit
A hívókörnyezet ref-safe-context-környezetével rendelkező variable_reference hivatkozási visszatérés hivatkozása lehet.
Ezek az értékek beágyazási kapcsolatot alkotnak a legszűkebbtől (deklarációs blokktól) a legszélesebbig (hívó-környezet). Minden beágyazott blokk egy másik környezetet jelöl.
Példa: Az alábbi kód a különböző ref-safe-contexts példákat mutatja be. A deklarációk egy változó inicializálási kifejezésének mutatják egy hivatkozó ref-safe-környezetét
ref. A példák a hivatkozási visszatérés ref-safe-context értékét mutatják be: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 is not 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]; } }záró példa.
Példa: Típusok esetén
structaz implicitthisparaméter referenciaparaméterként lesz átadva. A függvénytagként megadott típusú mezőkstructref-safe-contextje megakadályozza, hogy hivatkozási visszatéréssel visszaadja ezeket a mezőket. Ez a szabály megakadályozza a következő kódot: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 } }záró példa.
9.7.2.2 Helyi változó – biztonságos környezet
Helyi változó vesetén:
- Ha
vreferenciaváltozó, akkor a ref-safe-context értéke megegyezik az inicializáló kifejezés ref-safe-környezetével. - Ellenkező esetben a ref-safe-context deklarálási blokk.
9.7.2.3 Paraméter – biztonságos környezet
Paraméter pesetén:
- Ha
preferencia- vagy bemeneti paraméter, akkor a ref-safe-context a hívókörnyezet. Hapegy bemeneti paraméter, az nem írhatókéntrefadható vissza, de visszaadható.ref readonly - Ha
pkimeneti paraméter, akkor a ref-safe-context a hívókörnyezet. - Ellenkező esetben, ha
pegythisstruktúratípus paramétere, a ref-safe-context a függvény-tag. - Ellenkező esetben a paraméter egy értékparaméter, a ref-safe-context pedig a függvénytag.
9.7.2.4 A mező ref biztonságos környezete
Mezőre mutató hivatkozást e.Fkijelölő változó esetén:
- Ha
ereferenciatípus, akkor a ref-safe-context a hívókörnyezet. - Ellenkező esetben, ha
eérték típusú, a ref-safe-context megegyezik a ref-safe-context ofe.
9.7.2.5 Operátorok
A feltételes operátor (12.21. §) c ? ref e1 : ref e2és a referencia-hozzárendelési operátor = ref e (12.24.1. §) operandusként referenciaváltozókkal rendelkezik, és egy referenciaváltozót eredményez. Ezen operátorok esetében az eredmény ref-safe-contextje a legszűkebb kontextus az összes ref operandus ref-safe-contexts környezetei között.
9.7.2.6 Függvényhívás
A ref-returning függvény meghívásából eredő változók c esetében a ref-safe-context a legszűkebb az alábbi környezetek közül:
- A hívó környezet.
- Az összes
ref,outésinargumentumkifejezés ref-safe-contextje (a fogadó kivételével). - Minden bemeneti paraméter esetében, ha van egy változónak megfelelő kifejezés, és létezik identitáskonverzió a változó típusa és a paraméter típusa között, akkor a változó ref-safe-contextje, ellenkező esetben a legközelebbi beágyazási környezet.
- Az összes argumentumkifejezés (beleértve a fogadót is) biztonságos környezete (16.4.15. §).
Példa: az utolsó listajelre van szükség a kód kezeléséhez, például
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; }záró példa
A tulajdonsághívást és az indexelő-meghívást (vagy getset) a fenti szabályok az alapul szolgáló tartozék függvényhívásaként kezelik. A helyi függvényhívás függvényhívás.
9.7.2.7 Értékek
Az érték ref-safe-contextje a legközelebbi beágyazási környezet.
Megjegyzés: Ez egy olyan meghívásban fordul elő, mint például
M(ref d.Length)a wheredis of typedynamic. A bemeneti paramétereknek megfelelő argumentumokkal is összhangban van. végjegyzet
9.7.2.8 Konstruktor-meghívások
A new konstruktort meghívó kifejezés ugyanazokat a szabályokat követi, mint egy metódushívás (§9.7.2.6), amely a létrehozott típust adja vissza.
9.7.2.9 A referenciaváltozók korlátozásai
- Sem a lambda kifejezés, sem a helyi függvény nem rögzíthet referenciaparamétert, sem kimeneti paramétert, sem bemeneti paramétert, sem
refhelyi paramétert vagy helyi típustref struct. - Sem a referenciaparaméter, sem a kimeneti paraméter, sem a bemeneti paraméter, sem a
ref structtípus paramétere nem lehet argumentum az iterátor módszer vagy metódusasyncszámára. - Sem a
refhelyi, sem a helyiref structtípusú nem lehet kontextusban egyyield returnállítás vagy kifejezésawaitpontján. - Újbóli hozzárendelés
e1 = ref e2esetén a ref-safe-contextneke2legalább olyan szélesnek kell lennie , mint a ref-safe-context ofe1. - A ref return utasítás
return ref e1esetében a ref-safe-context ae1hívó kontextusa.
ECMA C# draft specification