C#基礎 繼承和實例化


有代碼如下,問輸出的是多少:

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 private 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

    }
}
IL代碼

最后打斷點,找到了原因

原因分析:

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的實例化就完成了

 

關鍵點:實例化類的時候,會先執行繼承的父類的構造函數,如果父類構造函數含有虛方法又會回調子類的重寫方法,之后才回到初始類的構造函數


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM