c#成員的初始化順序你真的非常清楚嗎,我發現有點坑爹,坑到爹突然有點搞不清楚什麼狀況。下面咱們開始分析,先看
3個簡單類。
public如果執行下面這段**會輸出什麼值呢,請不要往下看,先給出你自己的答案。abstract
class
base
public
abstract
void
setvalue();
}public
class
sub : base
public
override
void
setvalue()
}public
class
sub1 : base
}
static是的他很簡單,但你確信你的答案就是對的嗎?這麼乙個簡單的問題我答錯了,所以就有了這篇部落格。class
program
}
clr via c#這本書告訴我們:成員在定義的時候初始化相當於在建構函式的最上面初始化,如果乙個成員在定義的時候初始化,並在建構函式中賦值,那麼在建構函式執行完成之後,該成員的值就是造函式中所賦的值,所以我得出的答案都是:
c******han
。但答案不是這樣的。當執行結果出來時,我那個迷茫啊
.....
。先來說說我的簡單分析:
1:進入子類建構函式
2:sub成員變數的記憶體被分配
3:呼叫父類建構函式
4:呼叫子類的方法
setvalue
(子類覆寫了這個方法),
value
被賦值
5:正式執行子類建構函式,成員變數
value
再次被賦值
從上面5
步我得出他們輸出的結果一樣,都是
c******han
。錯在**呢?
於是我用reflector
檢視了一下,得到的結果正如上面所說,他們的原始碼是一樣的,如下所示。正如
clr via c#
這本書說的那樣,那為什麼結果不一樣呢,reflector
**是一樣的,執行的結果卻不一樣,怎麼回事,怎麼回事,那我只能說
reflector
坑爹,它不能反映程式的真正執行邏輯,非要我用
il,我用的還不熟呢。
public神馬情況,他們的ilclass
sub : base
public
override
void
setvalue()
}
**是不一樣的,如圖所示
看了這個圖,我們知道答案是c******han,
陳太漢。誰能告訴我怎麼呼叫父類的建構函式和給
value
賦值的順序不一樣啊。該用的工具都用了,我該怎麼證明這個結果,於是開始單步除錯,於是發現了乙個每天都發現了的秘密:
成員初始化在建構函式之前執行。
難怪這本書上說
成員在定義的時候初始化相當於在建構函式的最上面初始化,reflector
也證實了這個答案。但是又繞進另乙個坑爹的問題:建構函式還沒有呼叫
,記憶體還沒有分配,怎麼給成員變數賦值啊?這不是問題,從上圖可以看出成員變數的賦值只是在父類的建構函式之前呼叫,肯定也是在子類的成員變數分配空間之後為成員變數賦值。好的,最後我們得出的結論是:
1:進入子類建構函式
2:sub
成員變數的記憶體被分配
3:為sub
成員變數賦值
4:呼叫父類建構函式
5:呼叫子類的方法
setvalue
(子類覆寫了這個方法),
value
被賦值6:正式執行子類建構函式,成員變數
value
再次被賦值
這樣的解釋答案就很合理,但同時也說明成員變數在定義的時候初始化和在建構函式中賦值的意義是不一樣的,至少執行順序不一樣,產生的結果可能也不一樣。
部落格:
C 成員初始化有點坑爹
c 成員的初始化順序你真的非常清楚嗎,我發現有點坑爹,坑到爹突然有點搞不清楚什麼狀況。下面咱們開始分析,先看3個簡單類。public abstract class base public abstract void setvalue public class sub base public over...
C 成員初始化有點坑爹
c 成員的初始化順序你真的非常清楚嗎,我發現有點坑爹,坑到爹突然有點搞不清楚什麼狀況。下面咱們開始分析,先看 3個簡單類。public abstract class base public abstract void setvalue public class sub base public ove...
C 成員初始化列表
類物件的構造順序是這樣的 1.分配記憶體,呼叫建構函式時,隱式 顯示的初始化各資料成員 初始化階段可以是顯式的或隱式的,取決於是否存在成員初始化表。隱式初始化階段按照宣告的順序依次呼叫所有基類的預設建構函式,然後是所有成員類物件的預設建構函式。2.進入建構函式後在建構函式中執行一般計算 計算階段由建...