国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

C#LanguageSpecification5.0(翻譯)第五章變量

2019-11-14 14:07:48
字體:
供稿:網(wǎng)友

C# Language Specification 5.0

變量(variable)表示存儲(chǔ)的位置。每個(gè)變量都有類型,類型決定變量保存的值的類型。C# 是一門類型安全的語言,C# 編譯器會(huì)確保變量中保存一個(gè)適合類型的值。變量的值可通過賦值或通過使用 ++-- 操作符改變。

變量必須在獲得(obtained)前被明確賦值(definitely assigned)(第五章第三節(jié))。

如以下部分所述,變量要么初始已賦值(initially assigned),要么初始未賦值(initially unassigned)。初始已賦值的變量有非常明確(well-defined)的初始值,且視己為被明確賦值(definitely assigned)的。初始未賦值的變量沒有初始值(initial value)。對于初始未賦值變量來說,為了在某個(gè)位置能明確賦值,必須在通往該位置的每一個(gè)可能執(zhí)行到的分支對該變量賦值。


變量種類

C# 定義了七種變量:靜態(tài)變量(static variables)、實(shí)例變量(instance variables)、數(shù)組元素(array elements)、值參數(shù)(value parameters)、引用參數(shù)(reference parameters)、輸出參數(shù)(output parameters)和局部變量(local variables)。本節(jié)將對上述類型逐一介紹。

下例中

class A{    public static int x;    int y;    void F(int[] v, int a, ref int b, out int c) {        int i = 1;        c = a + b++;    }}

x 是靜態(tài)變量,y 是實(shí)例變量,v[0] 是數(shù)組元素,a 是值參數(shù),b 是引用參數(shù),c 是輸出參數(shù),i 是局部變量。

靜態(tài)變量

以靜態(tài)修飾符 static 聲明的字段被稱為靜態(tài)變量(static variable)。靜態(tài)變量在其所在類型的靜態(tài)構(gòu)造函數(shù)(第十章第十二節(jié))執(zhí)行之前便已存在,當(dāng)其所相關(guān)的應(yīng)用域(application domain)退出時(shí)不再存在。

靜態(tài)變量的初始值是其類型的默認(rèn)值(第五章第二節(jié))。

為了明確賦值檢查,靜態(tài)變量被視為初始已賦值的。

實(shí)例變量

不以靜態(tài)修飾符 static 聲明的字段叫做實(shí)例變量(instance variable)

類中的實(shí)例變量

類的實(shí)例變量在該類被創(chuàng)建實(shí)例時(shí)開始存在,當(dāng)所有對該實(shí)例的引用都終止、實(shí)例析構(gòu)函數(shù)(若有)執(zhí)行過后,該類的實(shí)例變量不再存在。

類實(shí)例變量的初始值是該變量類型的默認(rèn)值(第五章第二節(jié))。

為了明確賦值檢查,類的實(shí)例變量被認(rèn)為是初始已賦值的。

結(jié)構(gòu)中的實(shí)例變量

結(jié)構(gòu)實(shí)例變量的生命周期與其所屬的結(jié)構(gòu)變量是一樣的。換句話說,當(dāng)結(jié)構(gòu)類型的變量存在或終止時(shí),它的實(shí)例變量也隨之存在或消失。

結(jié)構(gòu)的實(shí)例變量的初始賦值狀態(tài)與其所在的結(jié)構(gòu)變量一樣。換句話說,當(dāng)結(jié)構(gòu)變量被視為初始化已賦值時(shí),其實(shí)例變量也被視為初始化已賦值;當(dāng)結(jié)構(gòu)變量被視為初始化未賦值時(shí),其實(shí)例變量也為初始化未賦值。

數(shù)組元素

當(dāng)數(shù)組實(shí)例被創(chuàng)建時(shí),數(shù)組元素開始存在;當(dāng)沒有任何引用指向該數(shù)組實(shí)例時(shí),數(shù)組元素消失。

數(shù)組的每一個(gè)元素的初始值均為該數(shù)組元素類型的默認(rèn)值(第五章第二節(jié))。

為了明確賦值檢查,數(shù)組元素被認(rèn)為是初始已賦值的。

值參數(shù)

不使用 refout 修飾符的參數(shù)聲明叫做值參數(shù)(value parameter)

值形參再調(diào)用該參數(shù)所屬的函數(shù)成員(方法、實(shí)例構(gòu)造函數(shù)、訪問器或操作符)或匿名函數(shù)時(shí)開始存在,并由調(diào)用者提供的實(shí)參的值初始化。一般來說,值形參的存在直到函數(shù)成員或匿名函數(shù)返回結(jié)果為止。然而,如果值形參如果被匿名函數(shù)(第七章第十五節(jié))捕獲(capture),則其生命周期將被至少延長到由該匿名函數(shù)創(chuàng)建的委托或表達(dá)式樹可被垃圾回收為止。

為了明確賦值檢查,值參數(shù)被認(rèn)為是初始已賦值的。

引用參數(shù)

使用 ref 修飾符的參數(shù)聲明叫做引用參數(shù)(reference parameter)

引用形參不會(huì)創(chuàng)建新的本地存儲(chǔ)位置。相反,引用形參表示其存儲(chǔ)位置與函數(shù)成員或匿名函數(shù)調(diào)用所給定的實(shí)參的存儲(chǔ)位置是一樣的。因此,引用形參的值總是與基礎(chǔ)變量相同。

下面的明確賦值規(guī)則適用于引用形參。注意,對輸出形參(output parameters)規(guī)則與第五章第 1.6 節(jié)中所描述的規(guī)則不同。

  • 變量必須在它被以引用參數(shù)形式傳入函數(shù)成員或委托調(diào)用之前被明確賦值(第五章第三節(jié))。
  • 在函數(shù)成員或匿名函數(shù)內(nèi),引用形參被視為已被賦值。

在結(jié)構(gòu)類型的實(shí)例方法或?qū)嵗L問器中,this 關(guān)鍵字的行為與該結(jié)構(gòu)類型所引用的形參相同(第七章第 6.7 節(jié))。

輸出參數(shù)

使用 out 修飾符的參數(shù)聲明叫做輸出參數(shù)(output parameter)

輸出形參不會(huì)創(chuàng)建新的本地存儲(chǔ)位置。相反,輸出形參表示與函數(shù)成員或委托調(diào)用所給定的存儲(chǔ)位置是一樣的。因此,輸出形參的值總是與基礎(chǔ)變量相同。

下面的明確賦值規(guī)則適用于輸出形參。注意,對引用形參(reference parameters)規(guī)則與第五章第 1.5 節(jié)中所描述的規(guī)則不同。

  • 變量不必在以輸出形參的方式傳入函數(shù)成員或委托調(diào)用之前明確初始化。
  • 在正常完成函數(shù)成員或委托調(diào)用之后,每一個(gè)以輸出形參的形式傳入的變量都被認(rèn)為在執(zhí)行路徑(execution path)中賦值。
  • 在函數(shù)成員或匿名函數(shù)內(nèi)部,輸出形參被視為初始未賦值。
  • 每一個(gè)函數(shù)成員或匿名函數(shù)的輸出形參必須在函數(shù)成員或匿名函數(shù)正常返回結(jié)果之前被明確賦值(第五章第三節(jié))。

在結(jié)構(gòu)類型的實(shí)例方法中,this 關(guān)鍵字的行為與該結(jié)構(gòu)類型所輸出的形參相同(第七章第 6.7 節(jié))。

局部變量

局部變量(local variable)local-variable-declaration 所聲明,可出現(xiàn)在 blockfor-statementswitch-statementusing-statement 內(nèi);或由 foreach-statementspecific-catch-clausetry-statement 聲明。

局部變量的生命周期是程序執(zhí)行期間的一部分,在此期間定會(huì)為其保留存儲(chǔ)。這個(gè)生命周期至少從進(jìn)入相關(guān)的 blockfor-statementswitch-statementusing-statementforeach-statementspecific-catch-clause 開始,到該 blockfor-statementswitch-statementusing-statementforeach-statementspecific-catch-clause 以任何方式結(jié)束為止。(進(jìn)入閉包的 block 或方法調(diào)用會(huì)掛起(suspends)——但不會(huì)結(jié)束——當(dāng)前的 blockfor-statementswitch-statementusing-statementforeach-statementspecific-catch-clause。)如果局部變量被匿名函數(shù)(第七章第 15.5.1 節(jié))捕獲,其生命周期至少延長到從該匿名函數(shù)創(chuàng)建的委托或表達(dá)式樹,以及其它引用該捕獲變量的對象可被垃圾回收為止。

如果遞歸地進(jìn)入(entered recursively)父 blockfor-statementswitch-statementusing-statementforeach-statementspecific-catch-clause,每次都會(huì)創(chuàng)建該局部變量的新實(shí)例,并重新計(jì)算其 local-variable-initializer(若有)。

local-variable-declaration 引入的局部變量不會(huì)自動(dòng)初始化,因此沒有默認(rèn)值。為了明確賦值檢查的目的,由 local-variable-declaration 引入的局部變量被認(rèn)為是初始未賦值(initially unassigned)的。local-variable-declaration 可以包括 local-variable-initializer,在此情況下,位于初始化表達(dá)式(第五章第 3.3.4 節(jié))之后的變量被視作明確賦值的。

local-variable-declaration 引入的局部變量的范圍內(nèi),在 local-variable-declarator 文本位置之前引用該局部變量會(huì)導(dǎo)致「編譯時(shí)錯(cuò)誤」。如果局部變量的聲明是隱式的(第八章第 5.1 節(jié)),那么在 local-variable-declarator 內(nèi)引用該變量同樣會(huì)報(bào)錯(cuò)。

foreach-statementspecific-catch-clause 引入的局部變量在整個(gè)范圍內(nèi)被視作明確賦值的。

局部變量的實(shí)際生命周期是依賴于具體實(shí)現(xiàn)的(implementation-dependent)。比方說,編譯器可能靜態(tài)地(statically)決定某個(gè)塊中的局部變量只用于該塊的一小部分(a small portion of that block)。基于此分析,編譯器生成的代碼可能會(huì)使該變量的存儲(chǔ)生命周期短于其所在的塊。

局部引用變量所引用的存儲(chǔ)(storage)的回收(reclaimed)獨(dú)立于該局部引用變量(第三章第九節(jié))的生命周期


默認(rèn)值

下列分類的變量將自動(dòng)初始化其默認(rèn)值:

  • 靜態(tài)變量;
  • 類實(shí)例的實(shí)例變量;
  • 數(shù)組元素。

變量默認(rèn)值依賴于其變量類型,并由以下規(guī)定確定:

  • 對于值類型的變量,默認(rèn)值與該值類型的默認(rèn)構(gòu)造函數(shù)(第四章第 1.2 節(jié))所計(jì)算出的值相同;
  • 對于引用類型的變量,默認(rèn)值為空 null。

默認(rèn)值初始化是一般是內(nèi)存管理器(memory manager)或垃圾回收器(garbage collector)在分配內(nèi)存給其使用之前,將內(nèi)存的「所有位置零(all-bits-zero)」。基于此,很方便使用「所有位置零」表示空引用(null reference)。


明確賦值

在函數(shù)成員可執(zhí)行代碼中的給定位置,如果編譯器能夠通過特別的靜態(tài)流程分析(particular static flow analysis,第五章第 3.3 節(jié))證明變量已被自動(dòng)初始化(automatically initialized)或至少一次被作為賦值的目標(biāo),那么稱變量已被明確賦值。非正式地來講,明確賦值的規(guī)則如下:

  • 初始已賦值變量(第五章第 3.1 節(jié))被視作明確賦值的。
  • 如果所有可能的通向指定位置的執(zhí)行路徑至少包含以下一條,那么稱初始未賦值變量(第五章第 3.2 節(jié))可被視為明確賦值的:
    • 將變量作為左操作數(shù)(left Operand)進(jìn)行簡單賦值(simple assignment,第七章第 17.1 節(jié))。
    • 將變量傳輸?shù)捷敵鰠?shù)作為調(diào)用表達(dá)式(invocation exPRession,第七章第 6.5 節(jié))或?qū)ο髣?chuàng)建表達(dá)式(object creation expression,第七章第 6.10.1 節(jié))。
    • 對于局部變量,包含變量初始化器(variable initializer)的局部變量聲明(第八章第 5.1 節(jié))。

對于以上這些非正式的規(guī)則的正式規(guī)范在第五章第 3.1 節(jié)、第五章第 3.2 節(jié)以及第五章第 3.3 節(jié)中介紹。

對于 struct-type 變量之實(shí)例變量的明確賦值狀態(tài),既可以單獨(dú)跟蹤(tracked individually),也可以整體跟蹤(tracked collectively)。另外除上述規(guī)則外,下列規(guī)則也將應(yīng)用于 struct-type 變量及其實(shí)例變量:

  • 當(dāng)實(shí)例變量包含已被視作明確賦值的 struct-type 變量時(shí),被視作已被明確賦值;
  • 當(dāng) struct-type 變量的每個(gè)實(shí)例變量都視作明確賦值時(shí),它也被視作明確賦值。

下列上下文是必須明確賦值的:

  • 變量必須在被獲得之前的每一個(gè)地方明確賦值,以確保不會(huì)出現(xiàn)未定義值。表達(dá)式中出現(xiàn)的變量被視作獲取變量的值,除非當(dāng):
    • 變量時(shí)簡單賦值的左操作數(shù),
    • 變量傳遞為一個(gè)輸出參數(shù),或者
    • 變量是 struct-type 變量且作為成員訪問的左操作數(shù)出現(xiàn)。
  • 變量必須在作為引用參數(shù)(reference parameter)傳遞的每個(gè)位置明確賦值,以確保被調(diào)用的函數(shù)成員能夠調(diào)用將之視作初始已賦值。
  • 所有函數(shù)成員的輸出參數(shù)必須在函數(shù)成員返回的每一個(gè)位置上明確賦值(通過 return 語句或通過執(zhí)行到函數(shù)成員體的尾部并返回),以確保函數(shù)成員不會(huì)在輸出參數(shù)中返回未定義的值(undefined values),因此允許編譯器把將變量作為輸出參數(shù)的函數(shù)成員的調(diào)用視作等價(jià)于對變量的賦值。
  • struct-type 實(shí)例構(gòu)造函數(shù)的 this 變量必須在實(shí)例構(gòu)造函數(shù)所返回的每一個(gè)位置上明確賦值。

初始已賦值變量

以下變量分類被歸入初始已賦值(initially assigned):

  • 靜態(tài)變量
  • 類實(shí)例的實(shí)例變量
  • 初始已賦值的結(jié)構(gòu)變量的實(shí)例變量
  • 數(shù)組元素
  • 值參數(shù)
  • 引用參數(shù)
  • 在 catch 子句 或 foreach 語句中的變量聲明

初始未賦值變量

以下變量分類被歸入初始未賦值(initially unassigned):

  • 初始未賦值的結(jié)構(gòu)變量的實(shí)例變量
  • 輸出參數(shù),包括結(jié)構(gòu)實(shí)例構(gòu)造函數(shù)的 this 變量
  • 局部變量,除了那些聲明于 catch 子句或 foreach 語句的變量

明確賦值的詳細(xì)規(guī)則

為了確定每個(gè)所用變量是否已明確賦值,編譯器必須使用與本節(jié)所述之一等價(jià)的處理過程。

編譯器會(huì)處理每一個(gè)具有至少一個(gè)初始未賦值變量的函數(shù)成員的主體。對于每一個(gè)初始未賦值的變量 v,編譯器在以下函數(shù)成員內(nèi)節(jié)點(diǎn)確定其明確賦值狀態(tài):

  • 位于每句語句的開頭位置
  • 位于每句語句的結(jié)束點(diǎn)(end point,第八章第一節(jié))
  • 在每個(gè)將控制轉(zhuǎn)移到另一句語句或語句結(jié)束點(diǎn)的 arc(Automatic Reference Counting)[1]
  • 位于每個(gè)表達(dá)式的開頭位置
  • 位于每個(gè)表達(dá)式的結(jié)尾位置

v 的明確賦值狀態(tài)可以是:

  • 明確賦值的(definitely assigned)。這表明在所有可以到達(dá)該點(diǎn)的控制流中,v 都已經(jīng)賦值。
  • 未明確賦值的(not definitely assigned)。對于位于 bool 類型表達(dá)式結(jié)尾處變量狀態(tài),其變量狀態(tài)為未明確賦值的可能(但不一定)分成下列子狀態(tài)(sub-states):
    • 在 true 表達(dá)式后明確賦值。這個(gè)狀態(tài)表明如果 bool 表達(dá)式運(yùn)算結(jié)果為 true 時(shí) v 將明確賦值,但當(dāng)其運(yùn)算結(jié)果為 false 時(shí)則不一定。
    • 在 false 表達(dá)式時(shí)候明確賦值。這個(gè)狀態(tài)表明如果 bool 表達(dá)式運(yùn)算結(jié)果為 false 時(shí) v 將明確賦值,但當(dāng)其運(yùn)算結(jié)果為 true 時(shí)則不一定。

下列規(guī)則控制變量 v 在每一個(gè)位置上如何決定明確賦值狀態(tài)的。

一般語句規(guī)則

  • 位于函數(shù)成員主體開頭處的 v 是未明確賦值的;
  • 在任何無法訪問的語句的開頭處的 v 都是明確賦值的;
  • 在任何其它語句開頭處 v 的明確賦值狀態(tài)由檢查 v 在所有指向該語句開始處的控制流轉(zhuǎn)移上的明確賦值狀態(tài)所決定的。當(dāng)且僅當(dāng) v 在所有此種控制流轉(zhuǎn)移上是明確賦值的,那么 v 才在語句開頭處是明確賦值的。確定所有可能的控制流轉(zhuǎn)移集的方法與檢查語句可訪問性的方法(第八章第一節(jié))相同。
  • 在 block、checked、unchecked、if、while、do、for、foreach、lock、using 或 switch 語句結(jié)尾點(diǎn)上的 v 的明確賦值狀態(tài)由檢查所有指向該語句結(jié)尾點(diǎn)的控制流轉(zhuǎn)移上 v 明確服裝狀態(tài)所決定。如果 v 在所有此種控制流轉(zhuǎn)移上是明確賦值的,那么 v 才在語句結(jié)尾點(diǎn)上是明確賦值的。不然的話,v 在語句結(jié)尾點(diǎn)上是未明確賦值的。確定所有可能的控制流轉(zhuǎn)移集的方法與檢查語句可訪問性的方法(第八章第一節(jié))相同。

塊、checked 與 unchecked 語句

在指向某塊(block)語句列表(statement list)中第一句語句(如果語句列表為空(empty)則指向該塊結(jié)束點(diǎn))的控制轉(zhuǎn)移上 v 的明確賦值狀態(tài)與語句、checked 或 unchecked 語句之前的 v 的明確賦值狀態(tài)一致。

表達(dá)式語句

對于由表達(dá)式 expr 組成的表達(dá)式語句 stmt

  • 位于 expr 開頭位置的 v 的明確賦值狀態(tài)與 stmt 開頭處的一致;
  • 如果 v 在 expr 結(jié)尾處是明確賦值的,那么在 stmt 結(jié)尾點(diǎn)也是明確賦值的,不然相反。

聲明語句

  • 如果 stmt 是不帶初始化器的聲明語句,則 v 在 stmt 結(jié)束點(diǎn)與在 stmt 開頭處具有相同的明確賦值狀態(tài);
  • 如果 stmt 是一個(gè)帶初始化器的聲明語句,則確定 v 的明確賦值狀態(tài)時(shí)可將之視為語句列表,每個(gè)帶初始化器的聲明對應(yīng)一句賦值語句(按聲明的順序)。

if 語句

對于形如以下的 if 語句 stmt

if ( expr ) then-stmt else else-stmt
  • 位于 expr 開頭位置的 v 的明確賦值狀態(tài)與 stmt 開頭處一致;
  • 如果 v 在 expr 結(jié)尾處是明確賦值的,那么在指向 then-stmt 以及任意一個(gè) else-stmtstmt 結(jié)尾點(diǎn)(如果沒有 else 子句)的控制流轉(zhuǎn)移上是明確賦值的;
  • 如果 v 在 expr 結(jié)尾處的狀態(tài)是「在 true 表達(dá)式之后明確賦值」,那么在指向 then-stmt 的控制流轉(zhuǎn)移上是明確賦值的,但指向 else-stmtstmt 的結(jié)尾點(diǎn)(如果沒有 else 子句)的控制流轉(zhuǎn)移上是未明確賦值的;
  • 如果 v 在 expr 結(jié)尾點(diǎn)的狀態(tài)是「在 false 表達(dá)式之后明確賦值」,那么在指向 else-stmt 的控制流轉(zhuǎn)移上是明確賦值的,但指向 then-stmt 的控制流轉(zhuǎn)移上是未明確賦值的。位于 stmt 結(jié)束點(diǎn)(當(dāng)且僅當(dāng)在 then-stmt 結(jié)尾點(diǎn)是明確賦值的)上是明確賦值的。
  • 否則的話,位于指向任意一個(gè) then-stmtelse-stmtstmt 結(jié)尾點(diǎn)(如果沒有 else 子句)的控制流轉(zhuǎn)移上的 v 被視作未明確賦值。

switch 語句

在帶有控制表達(dá)式 expr 的 switch 語句 stmt

  • 位于 expr 開始位置的 v 的明確賦值狀態(tài)與位于 stmt 開頭位置的 v 的狀態(tài)是一致的;
  • 在指向一個(gè)可訪問(reachable)的 switch 語句塊列表的控制流轉(zhuǎn)移上 v 明確賦值狀態(tài)就是 expr 結(jié)尾處的明確賦值狀態(tài)。

while 語句

對于形如以下的 while 語句 stmt

while ( expr ) while-body
  • 位于 expr 開頭位置的 v 的明確賦值狀態(tài)與 stmt 開頭處的一致;
  • 如果 v 在 expr 結(jié)尾處是明確賦值的,那么在指向 while-body 的控制流轉(zhuǎn)移上以及在 stmt 結(jié)尾點(diǎn)上的狀態(tài)是明確賦值的;
  • 如果 v 在 expr 結(jié)尾點(diǎn)的狀態(tài)是「在 true 表達(dá)式之后明確賦值」,那么在指向 while-body 的控制流轉(zhuǎn)移上它是明確賦值的,但在 stmt 結(jié)尾點(diǎn)上是未明確賦值的;
  • 如果 v 在 expr 結(jié)尾點(diǎn)的狀態(tài)是「在 false 表達(dá)式之后明確賦值」,那么在指向 stmt 結(jié)尾點(diǎn)的控制流轉(zhuǎn)移上它是明確賦值的,單位指向 while-body 的控制流轉(zhuǎn)移上它未明確賦值的。

do 語句

do 語句的明確賦值檢查有以下形式:

do do-body while ( expr ) ;
  • 位于 stmt 開頭處到 do-body 的控制流轉(zhuǎn)移(control flow transfer)上的 v 的明確賦值狀態(tài)與 stmt 開頭處的一致。
  • 位于 expr 開頭處的 v 的明確賦值狀態(tài)與 do-body 結(jié)尾處的一致。
  • 如果位于 expr 結(jié)尾處 v 是明確賦值的,那么在 stmt 結(jié)尾處的控制硫轉(zhuǎn)移上的 v 也是明確賦值的。
  • 如果位于 expr 結(jié)尾處 v 具有「在 false 表達(dá)式之后明確賦值」,那么在 stmt 結(jié)尾處的控制硫轉(zhuǎn)移上的 v 也是明確賦值的。

for 語句

for 語句的明確賦值檢查有以下形式:

for ( for-initializer ; for-condition ; for-iterator ) embedded-statement

如下面所寫語句一樣:

{    for-initializer ;    while ( for-condition ) {        embedded-statement ;        for-iterator ;    }}

如果 for-condition 從語句中省略,則當(dāng)評估明確賦值狀態(tài)時(shí),可將上述展開語句中的 for-condition 當(dāng)做 true

break、continue 與 goto 語句

breakcontinuegoto 語句導(dǎo)致的控制流轉(zhuǎn)移(control flow transfer)上 v 的明確賦值狀態(tài)與語句開始處 v 的明確賦值狀態(tài)一致。

throw 語句

對于以下形式的語句 stmt

throw expr ;

位于 expr 開頭處 v 的明確賦值狀態(tài)與 stmt 開頭處 v 的狀態(tài)一致。

return 語句

對于以下形式的語句 stmt

return expr ;
  • 位于 expr 開頭 v 的明確賦值狀態(tài)與 stmt 開頭 v 的狀態(tài)是一致的。
  • 如果 v 是輸出形參,則其必須明確賦值(二選一):
    • 要么在 expr 之后;
    • 要么在閉包于 return 語句的 try-finallytry-catch-finallyfinally 塊的結(jié)尾處。

對于以下形式的語句 stmt

return ;
  • 如果 v 是輸出形參,則其必須明確賦值(二選一):
    • 要么在 stmt 之前;
    • 要么在閉包于 return 語句的 try-catchtry-catch-finallyfinally 塊的結(jié)尾處。

try-catch 語句

對于以下形式的語句 stmt

try try-blockcatch(...) catch-block-1...catch(...) catch-block-n
  • 位于 try-block 開始處的 v 的明確賦值狀態(tài)與 stmt 開頭處一致;
  • 位于 catch-block-i 開始處(對于任意 i)的 v 的明確賦值狀態(tài)與 stmt 開頭處一致;
  • 當(dāng)且僅當(dāng) v 位于 try-block 結(jié)尾點(diǎn)和每一個(gè) catch-block-i(i ∈ [1, n])的結(jié)尾點(diǎn)是明確賦值的,則位于 stmt 結(jié)尾點(diǎn)的 v 的明確賦值狀態(tài)是明確賦值的。

try-finally 語句

對于以下形式的 try 語句 stmt

try try-block finally finally-block
  • 位于 try-block 開始處的 v 的明確賦值狀態(tài)與 stmt 開頭處一致;
  • 位于 finally-block 開始處的 v 的明確賦值狀態(tài)與 stmt 開頭處一致;
  • 當(dāng)且僅當(dāng)至少滿足以下一條條件時(shí),位于 stmt 結(jié)尾點(diǎn)的 v 的明確賦值狀態(tài)是明確賦值的:
    • v 在 try-block 結(jié)束點(diǎn)是明確賦值的;
    • v 在 finally-bolck 結(jié)束點(diǎn)是明確賦值的。

如果控制流轉(zhuǎn)移(比方說,一個(gè) goto 語句)從 try-block 內(nèi)開始,結(jié)束于 try-block 外,那么如果 v 在 finally-block 的結(jié)束點(diǎn)上明確賦值,在控制流轉(zhuǎn)移上 v 同樣被視作明確賦值的(這不是必要條件,如果 v 在 finally-block 結(jié)束點(diǎn)上是明確賦值的,那么它任被視作明確賦值)。

try-catch-finally 語句

對于形如下面這段 try-catch-finally 的明確賦值分析

try try-block catch(...) catch-block-1...catch(...) catch-block-nfinally finally-block

與將 try-catch 語句閉包于 try-finally 內(nèi)的效果一樣:

try {    try try-block     catch(...) catch-block-1    ...    catch(...) catch-block-n}finally finally-block

下例演示了明確賦值在不同 try 語句塊(第八章第十節(jié))中的效果。

class A{    static void F() {        int i, j;        try {            goto LABEL;            // i 和 j 都沒有明確賦值            i = 1;            // i 明確賦值        }        catch {            // i 和 j 都沒有明確賦值            i = 3;            // i 明確賦值        }        finally {            // i 和 j 都沒有明確賦值            j = 5;            // j 明確賦值        }        // i and j 明確賦值        LABEL:;        // j 明確賦值    }}

foreach 語句

對于以下形式的 foreach 語句 stmt

foreach ( type identifier in expr ) embedded-statement
  • 位于 expr 開頭處的 v 的明確賦值狀態(tài)與 stmt 開頭處的一致;
  • 位于指向 embedded-statement 的控制流轉(zhuǎn)移上的 v 的明確賦值狀態(tài)與 expr 結(jié)尾處的一致。

using 語句

對于以下形式的 using 語句 stmt

using ( resource-acquisition ) embedded-statement
  • 位于 resource-acquisition 開頭處的 v 的明確賦值狀態(tài)與 stmt 開頭處的一致;
  • 位于指向 embedded-statement 的控制流轉(zhuǎn)移上的 v 的明確賦值狀態(tài)與 resource-acquisition 結(jié)尾處的一致。

lock 語句

對于以下形式的 lock 語句 stmt

lock ( expr ) embedded-statement
  • 位于 expr 開頭處的 v 的明確賦值狀態(tài)與 stmt 開頭處的一致;
  • 位于指向 embedded-statement 的控制流轉(zhuǎn)移上的 v 的明確賦值狀態(tài)與 expr 結(jié)尾處的一致。

yield 語句

對于以下形式的 yield return 語句 stmt

yield return expr ;
  • 位于 expr 開頭 v 的明確賦值狀態(tài)與 stmt 開頭 v 的狀態(tài)是一致的。
  • 位于 stmt 結(jié)尾 v 的明確賦值狀態(tài)與 expr 結(jié)尾 v 的狀態(tài)是一致的。

yield break 語句對于明確定義狀態(tài)沒有影響。

簡單表達(dá)式的一般規(guī)則

以下規(guī)則可應(yīng)用于下諸類型之表達(dá)式:文本(literals,第七章第 6.1 節(jié))、簡單名稱(simple names,第七章第 6.2 節(jié))、成員訪問表達(dá)式(member access expressions,第七章第 6.4 節(jié))、非索引基訪問表達(dá)式(non-indexed base access expressions,第七章第 6.8 節(jié))、typeof 表達(dá)式(typeof expressions,第七章第 6.11 節(jié))以及默認(rèn)值表達(dá)式(default value expressions,第七章第 6.13 節(jié))。

  • 位于上述表達(dá)式結(jié)尾處 v 的明確賦值狀態(tài)與位于表達(dá)式開頭的 v 的狀態(tài)一致。

帶嵌入表達(dá)式的表達(dá)式一般規(guī)則

以下規(guī)則可應(yīng)用于下諸類型之表達(dá)式:帶括號(hào)的表達(dá)式(parenthesized expressions,第七章第 6.3 節(jié))、元素訪問表達(dá)式(element access expressions,第七章第 6.6 節(jié))、帶索引的基訪問表達(dá)式(base access expressions with indexing,第七章第 6.8 節(jié))、增量與減量表達(dá)式(increment and decrement expressions,第七章第 6.9 節(jié))、強(qiáng)制轉(zhuǎn)換表達(dá)式(cast expressions,第七章第 7.6 節(jié))、一元 +, -, ~, * 表達(dá)式、二元 +, -, *, /, %, <<, >>, <, <=, >, >=, ==, !=, is, as, &, |, ^ 表達(dá)式(第七章第 8、9、10、11 節(jié))、復(fù)合賦值表達(dá)式(compound assignment expressions, 第七章第 17.2 節(jié))、checkedunchecked 表達(dá)式(第七章第 6.12 節(jié))以及數(shù)組與委托創(chuàng)建表達(dá)式(array and delegate creation expressions,第七章第 6.10 節(jié))。

這些表達(dá)式包含一個(gè)或多個(gè)固定順序無條件計(jì)算(unconditionally evaluated in a fixed order)的子表達(dá)式(sub-expressions)。比方說,二元運(yùn)算符 % 先運(yùn)算左邊的值,然后運(yùn)算右邊的。索引操作先計(jì)算索引表達(dá)式(indexed expression),然后從左到右運(yùn)算每個(gè)索引表達(dá)式(index expressions)。對于具有子表達(dá)式 expr1、expr2、……、exprn 的表達(dá)式 expr,按下列順序執(zhí)行:

  • 位于 expr1 開頭的 v 的明確賦值狀態(tài)與 expr 開頭的狀態(tài)一致;
  • 位于 expri(i 大于 1) 開頭的 v 的明確賦值狀態(tài)與 exprn 結(jié)尾處 v 的狀態(tài)一致;
  • 位于 expr` 結(jié)尾處 v 的明確賦值狀態(tài)與 exprn 結(jié)尾處 v 的狀態(tài)一致。

調(diào)用表達(dá)式與對象創(chuàng)建表達(dá)式

對于以下形式的調(diào)用表達(dá)式(invocation expression)expr

primary-expression ( arg1 , arg2 , … , argn )

或以下形式的對象創(chuàng)建表達(dá)式(object creation expression):

new type ( arg1 , arg2 , … , argn )
  • 對于調(diào)用表達(dá)式,位于 primary-expression 前 v 的明確賦值狀態(tài)與 expr 前 v 的狀態(tài)一致。
  • 對于調(diào)用表達(dá)式,位于 arg1 之前 v 的明確賦值狀態(tài)與 primary-expression 后 v 的狀態(tài)是一致的。
  • 對于對象創(chuàng)建表達(dá)式,位于 arg1 之前 v 的明確賦值狀態(tài)與 expr 后 v 的狀態(tài)是一致的。
  • 對于每個(gè) argi 實(shí)參,位于 argi 之后 v 的明確賦值狀態(tài)是由標(biāo)準(zhǔn)表達(dá)式規(guī)則(normal expression rules)所決定的,其中忽略所有的 refout 修飾符。
  • 對于每個(gè) argi 實(shí)參(i 大于 1),位于 argi 之前 v 的明確賦值狀態(tài)與 argi-1 后 v 的狀態(tài)是一致的。
  • 如果變量 v 以輸出參數(shù)(形如 out v)的方式傳入實(shí)參,則 expr 后 v 的狀態(tài)是明確賦值的。否則的話,expr 后 v 的狀態(tài)與 argn 后 v 的狀態(tài)一致。
  • 對于數(shù)組初始化器(array initializers,第七章第 6.10.4 節(jié))、對象初始化器(object initializers,第七章第 6.10.2 節(jié))、集合初始化器(collection initializers,第七章第 6.10.3 節(jié))以及匿名對象初始化器(anonymous object initializers,第七章第 6.10.6 節(jié)),它們的明確賦值狀態(tài)取決于定義這些構(gòu)造所依據(jù)的擴(kuò)展所決定。

簡單賦值表達(dá)式

對于形如 w = expr-rhs 的表達(dá)式 expr

  • expr-rhs 之前的 v 的明確賦值狀態(tài)與在 expr 前 v 的明確賦值狀態(tài)是一樣的。
  • 如果 w 是與 v 是同一變量,則 expr 之后的 v 的明確賦值狀態(tài)為「已被明確扶植」。否則 expr 之后的 v 的明確賦值狀態(tài)與 expr-rhs 之后的 v 的明確賦值狀態(tài)是一樣的。

&& 表達(dá)式

對于形如 expr-first && expr-second 的表達(dá)式 expr

  • expr-first 之前的 v 的明確賦值狀態(tài)與在 expr 之前的 v 的明確賦值狀態(tài)是一樣的。
  • 如果 expr-first 之后的 v 是明確賦值的或「在 true 表達(dá)式之后明確賦值」,那么在 expr-second 之前的 v 的明確賦值狀態(tài)是明確賦值的。否則,它就不是明確賦值的。
  • expr 之后的 v 的明確賦值狀態(tài)取決于:
    • 如果 expr-first 是值為 false 的常量表達(dá)式,則 expr 之后的 v 的明確賦值狀態(tài)與在 expr-first 之后的 v 的狀態(tài)是一樣的。
    • 不然的話,如果 expr-first 之后的 v 的狀態(tài)是明確賦值的,那么 expr 之后的 v 的狀態(tài)也是明確賦值的。
    • 再不然,如果 expt-second 之后的 v 的狀態(tài)是明確賦值的、并且 expr-first 之后的狀態(tài)是「在 false 表達(dá)式之后明確賦值」,那么 expr 之后的 v 的狀態(tài)是已明確賦值的。
    • 否則,如果 expr-second 后的 v 的狀態(tài)是明確賦值或「在 true 表達(dá)式之后明確賦值」,那么 expr 之后 v 的狀態(tài)是「在 true 表達(dá)式之后明確賦值」。
    • 再不然,如果 expr-first 后 v 的狀態(tài)是「在 false 表達(dá)式之后明確賦值」且 expr-second 后 v 的狀態(tài)是「在 false 表達(dá)式之后明確賦值」,那么 expr 的 v 的狀態(tài)是「在 false 表達(dá)式之后明確賦值」。
    • 否則,expr 之后的 v 的狀態(tài)就是未明確賦值了。

在下例中

class A{    static void F(int x, int y) {        int i;        if (x >= 0 && (i = y) >= 0) {            // i 明確賦值        }        else {            // i 沒有明確賦值        }        // i 沒有明確賦值    }}

變量 i 在 if 語句的其中一個(gè)嵌入語句中被視作是明確賦值的,但在另一個(gè)則不是。在方法 F 的 if 語句中,變量 i 在第一個(gè)嵌入語句中被明確賦值,因?yàn)樵诒磉_(dá)式 (i = y) 執(zhí)行的時(shí)間先于這段嵌入語句的執(zhí)行時(shí)間。相反,變量 i 在第二個(gè)嵌入語句中是未明確賦值的,因?yàn)?x >= 0 為 false 時(shí)的結(jié)果是變量 i 未被賦值。

|| 表達(dá)式

對于形如 expr-first || expr-second 的表達(dá)式 expr

  • expr-first 前 v 的明確賦值狀態(tài)與 expr 前 v 的狀態(tài)是一樣的。
  • 如果 expr-first 后 v 的狀態(tài)是明確賦值或「在 false 表達(dá)式之后明確賦值」,那么在 expr-second 前 v 的狀態(tài)是已明確賦值的。否則的話,他就是未明確賦值的。
  • expr 后 v 的明確賦值狀態(tài)取決于:
    • 如果 expr-first 是值為 true 的常量表達(dá)式,則 expr 之后的 v 的明確賦值狀態(tài)與在 expr-first 之后的 v 的狀態(tài)是一樣的。
    • 不然的話,如果 expr-first 之后的 v 的狀態(tài)是明確賦值的,那么 expr 之后的 v 的狀態(tài)也是明確賦值的。
    • 再不然,如果 expt-second 之后的 v 的狀態(tài)是明確賦值的、并且 expr-first 之后的狀態(tài)是「在 true 表達(dá)式之后明確賦值」,那么 expr 之后的 v 的狀態(tài)是已明確賦值的。
    • 否則,如果 expr-second 后的 v 的狀態(tài)是明確賦值或「在 false 表達(dá)式之后明確賦值」,那么 expr 之后 v 的狀態(tài)是「在 false 表達(dá)式之后明確賦值」。
    • 再不然,如果 expr-first 后 v 的狀態(tài)是「在 true 表達(dá)式之后明確賦值」且 expr-second 后 v 的狀態(tài)是「在 true 表達(dá)式之后明確賦值」,那么 expr 的 v 的狀態(tài)是「在 true 表達(dá)式之后明確賦值」。
    • 否則,expr 之后的 v 的狀態(tài)就是未明確賦值了。

在下例中

class A{    static void G(int x, int y) {        int i;        if (x >= 0 || (i = y) >= 0) {            // i 沒有明確賦值        }        else {            // i 明確賦值        }        // i 沒有明確賦值    }}

變量 i 在其中一個(gè)嵌入語句中被視作明確賦值,而在另一個(gè)中則不是。在方法 G 的 if 語句中,變量 i 在第二個(gè)嵌入語句中被視作明確賦值,因?yàn)楸磉_(dá)式 (i = y) 的執(zhí)行將先于這段嵌入語句。與此相反,變量 i 在第一個(gè)嵌入語句中被視作未明確賦值,因?yàn)?x >= 0 可能為 true,那么作為其結(jié)果變量 i 沒有被賦值。

! 表達(dá)式

對于形如 ! expr-operand 的表達(dá)式 expr

  • expr-operand 前 v 的明確賦值狀態(tài)與 expr 前 v 的狀態(tài)是一樣的。
  • expr 后 v 的明確賦值狀態(tài)取決于:
    • 如果 expr-operand 后 v 的狀態(tài)是已明確賦值的,那么 expr 后 v 的狀態(tài)是已明確賦值的
    • 如果 expr-operand 后 v 的狀態(tài)是未明確賦值的,那么 expr 后 v 的狀態(tài)是未明確賦值的
    • 如果 expr-operand 后 v 的狀態(tài)是「在 false 表達(dá)式后明確賦值」,那么 expr 后 v 的狀態(tài)是「在 true 表達(dá)式后明確賦值」。
    • 如果 expr-operand 后 v 的狀態(tài)是「在 true 表達(dá)式后明確賦值」,那么 expr 后 v 的狀態(tài)是「在 false 表達(dá)式后明確賦值」。

?? 表達(dá)式

對于形如 expr-first ?? expr-second 的表達(dá)式 expr

  • expr-first 前 v 的明確賦值狀態(tài)與 expr 前 v 的狀態(tài)是一樣的。
  • expr-second 前 v 的明確賦值狀態(tài)與 expr-first 后 v 的狀態(tài)是一樣的。
  • expr 后 v 的明確賦值狀態(tài)取決于:
    • expr-first 是值為 null 的常量表達(dá)式(第七章第十九節(jié)),則 expr 后 v 的狀態(tài)與 expr-second 后 v 的狀態(tài)是一致的。
    • 否則的話,expr 后 v 的狀態(tài)與 expr-first 后 v 的明確賦值狀態(tài)一致。

?: 表達(dá)式

對于形如 expr-cond ? expr-true : expr-false 的表達(dá)式 expr

  • expr-cond 前 v 的明確賦值狀態(tài)與 expr 前 v 的狀態(tài)是一樣的。
  • 當(dāng)且僅當(dāng)滿足以下一條時(shí),在 expr-true 前 v 的明確賦值狀態(tài)是已明確賦值的:
    • expr-cond 是值為 false 的常量表達(dá)式。
    • expr-cond 后 v 的狀態(tài)是以明確賦值或「在 true 表達(dá)式后明確賦值」。
  • 當(dāng)且僅當(dāng)滿足以下一條時(shí),在 expr-false 前 v 的明確賦值狀態(tài)是已明確賦值的:
    • expr-cond 是值為 true 的常量表達(dá)式。
    • expr-cond 后 v 的狀態(tài)是以明確賦值或「在 false 表達(dá)式后明確賦值」。(注:原文此處有筆誤)
  • expr 后 v 的明確賦值狀態(tài)取決于:
    • expr-cond 是值為 true 的常量表達(dá)式(第七章第十九節(jié)),則 expr 后 v 的狀態(tài)與 expr-true 后 v 的狀態(tài)一致。
    • 不然,若 expr-cond 是值為 false 的常量表達(dá)式(第七章第十九節(jié)),則 expr 后 v 的狀態(tài)與 expr-false 后 v 的狀態(tài)一致。
    • 再不然,若 expr-true 后 v 的狀態(tài)是明確賦值,且 expr-false 后 v 的狀態(tài)也是明確賦值的,則 expr 后 v 的狀態(tài)同樣是明確賦值的。
    • 否則,expr 之后的 v 的狀態(tài)就是未明確賦值了。

匿名函數(shù)

對于具有主體(塊或表達(dá)式)的 Lambda 表達(dá)式(lambda-expression)或匿名方法表達(dá)式(anonymous-method-expression)expr 的主體(body):

  • body 之前的外部變量 v 的明確賦值狀態(tài)與 expr 之前的 v 的狀態(tài)是一樣的。也就是說,外部變量的明確賦值狀態(tài)繼承自匿名函數(shù)上下文。
  • expr 之后的外部變量 v 的明確賦值狀態(tài)與 expr 之前的 v 的狀態(tài)是一樣的。

舉例

delegate bool Filter(int i);void F() {    int max;    // 錯(cuò)誤,max 沒有明確賦值    Filter f = (int n) => n < max;    max = 5;    DoWork(f);}

由于在匿名函數(shù)被聲明的時(shí)候 max 沒有明確賦值,所以這將產(chǎn)生一個(gè)「編譯時(shí)錯(cuò)誤」。舉個(gè)例子。

delegate void D();void F() {    int n;    D d = () => { n = 1; };    d();    //錯(cuò)誤,n 沒有明確賦值    Console.WriteLine(n);}

由于在匿名函數(shù)之外對匿名函數(shù)內(nèi)部的 n 進(jìn)行明確賦值是沒有效果的,所以這同樣會(huì)產(chǎn)生一個(gè)「編譯時(shí)錯(cuò)誤」。


變量引用

變量引用(variable-reference)是一個(gè)被歸類到變量(variable)的表達(dá)式(expression)。變量引用表示一個(gè)存儲(chǔ)空間,通過訪問它可以獲取當(dāng)前值、保存新值。

variable-reference:    expression

在 C 和 C++ 中,變量引用(variable-reference)中稱為 lvalue


變量引用的原子性

讀寫以下數(shù)據(jù)類型是原子性的(atomic):boolcharbytesbyteshortushortuintintfloat 以及引用類型。另外,如果枚舉的基礎(chǔ)類型屬于上述列表內(nèi)的,則讀寫該枚舉值也是原子性的。讀寫其它類型,包括 longulongdoubledecimal 以及用戶自定義的類型時(shí),不能保證一定是原子的。除專門為該墓地設(shè)計(jì)的庫函數(shù)以外,對于增量(increment)或減量(decrement)這種情況,依舊不能保證原子性的讀取、修改與寫入(read-modify-write)。


[1]ARC:Automatic Reference Counting,自動(dòng)引用計(jì)數(shù),是開發(fā)程序時(shí)的一個(gè)編譯級別的特性,用于自動(dòng)內(nèi)存管理。更多請?jiān)L問此處以及此處。

__EOF__

C# Language Specification 5.0 翻譯計(jì)劃


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 弋阳县| 全南县| 承德县| 江西省| 南华县| 莱州市| 皮山县| 望城县| 五家渠市| 阳山县| 彩票| 横峰县| 绥芬河市| 凌云县| 长沙县| 察隅县| 仲巴县| 西安市| 合江县| 安徽省| 乌拉特后旗| 阿拉善左旗| 林口县| 常熟市| 甘孜| 凤冈县| 五常市| 营山县| 光泽县| 独山县| 苏尼特左旗| 西乌珠穆沁旗| 昌宁县| 玛多县| 高安市| 伊金霍洛旗| 滨州市| 滨海县| 太仆寺旗| 彰化市| 南召县|