C#基礎 繼承和實例化
阿新 • • 發佈:2019-01-10
[] lose pen als aps all ack spa bject
有代碼如下,問輸出的是多少:
class Program { static void Main(string[] args) { B b = new B(); Console.ReadKey(); } class A { public A() { PrintFields(); } public virtual void PrintFields() { } } class B : A {int x = 1; int y; public B() { y = -1; } public override void PrintFields() { Console.WriteLine("x={0},y={1}", x, y); } } }
結果:x=1;y=0;
剛開始有點不理解,覺得輸出是x=1;y=-1;然後反編譯看了下IL代碼,然而。。還是沒看出來,IL代碼如下:
.class privateIL代碼auto ansi beforefieldinit Program extends [mscorlib]System.Object { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: call instance void [mscorlib]System.Object::.ctor() L_0006: nop L_0007:ret } .method private hidebysig static void Main(string[] args) cil managed { .entrypoint .maxstack 1 .locals init ( [0] class ConsoleApplication1.Program/B b) L_0000: nop L_0001: newobj instance void ConsoleApplication1.Program/B::.ctor() L_0006: stloc.0 L_0007: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() L_000c: pop L_000d: ret } .class auto ansi nested private beforefieldinit A extends [mscorlib]System.Object { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: call instance void [mscorlib]System.Object::.ctor() L_0006: nop L_0007: nop L_0008: ldarg.0 L_0009: callvirt instance void ConsoleApplication1.Program/A::PrintFields() L_000e: nop L_000f: ret } .method public hidebysig newslot virtual instance void PrintFields() cil managed { .maxstack 8 L_0000: nop L_0001: ret } } .class auto ansi nested private beforefieldinit B extends ConsoleApplication1.Program/A { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: ldc.i4.1 L_0002: stfld int32 ConsoleApplication1.Program/B::x L_0007: ldarg.0 L_0008: call instance void ConsoleApplication1.Program/A::.ctor() L_000d: nop L_000e: nop L_000f: ldarg.0 L_0010: ldc.i4.m1 L_0011: stfld int32 ConsoleApplication1.Program/B::y L_0016: ret } .method public hidebysig virtual instance void PrintFields() cil managed { .maxstack 8 L_0000: nop L_0001: ldstr "x={0},y={1}" L_0006: ldarg.0 L_0007: ldfld int32 ConsoleApplication1.Program/B::x L_000c: box int32 L_0011: ldarg.0 L_0012: ldfld int32 ConsoleApplication1.Program/B::y L_0017: box int32 L_001c: call void [mscorlib]System.Console::WriteLine(string, object, object) L_0021: nop L_0022: ret } .field private int32 x .field private int32 y } }
最後打斷點,找到了原因
原因分析:
B b = new B();
執行順序:
1、int x = 1;int y;給x賦值1,給y賦值默認為0(int類型)
2、public B(),然後關鍵點來了
3、public A(),執行A裏面的PrintFields();但是A裏面的這個方法是個虛方法,會調用B裏面重寫的方法
4、public override void PrintFields()這個是B裏面的然後Console.WriteLine("x={0},y={1}", x, y);結果當然就是x=1;y=0;
5、然後才回到了B的public B(),接著給y賦值y = -1;這個時候y才變了,如果這個時候打印y的值才是-1,這個時候B的實例化就完成了
關鍵點:實例化類的時候,會先執行繼承的父類的構造函數,如果父類構造函數含有虛方法又會回調子類的重寫方法,之後才回到初始類的構造函數
C#基礎 繼承和實例化