CSDN社区C#版有人出基础题,我没事也做一下练练,今天做到一道题是这样的:
(原题链接:http://community.csdn.net/Expert/topic/3918/3918948.xml?temp=.2294428)

编写一个控制台应用程序,完成下列功能,并回答提出的问题。
1.创建一个类A,在构造函数中输出“A”,再创建一个类B,在构造函数中输出“B”。
2.从A继承一个名为C的新类,并在C内创建一个成员B。不要为C创建构造函数。
3.在Main方法中创建类C的一个对象,写出运行程序后输出的结果。
4.如果在C中也创建一个构造函数输出“C”,整个程序运行的结果又是什么?

要简单回到这道题是简单的,我的答案是:

 1using System;
 2
 3class A
 4{
 5    public A()
 6    {
 7        Console.WriteLine("A");
 8    }
 9}
10
11class B
12{
13    public B()
14    {
15        Console.WriteLine("B");
16    }
17}
18
19class C : A
20{
21    public C()
22    {
23        Console.WriteLine("C");
24    }
25    B b = new B();
26}
27
28class Test
29{
30    public static void Main()
31    {
32        C c = new C();
33        
34    }
35}

跟作者的参考答案是一致的,但是作者在结帖的时候并没有回答有人提出的一个问题:问什么是这样的输出顺序呢?

我就自己想了一下。首先看输出解结果“B”是调用B类的实例构造函数输出的,“A”是调用A类的构造函数输出的,“C”调用C类的构造函数输出的。
其中B类作为一个字段出现在C类中,而C类继承A类。那么,我猜,在主函数中构造C对象,首先初始化C类的字段,然后调用祖先类的构造函数,再实现C类自己构造函数中的代码,这样就解释了这种顺序。

那么这种猜想成不成立呢?

首先初始化C类的字段可能会有些疑惑,为什么非要先初始化类的字段呢?这里就扯到另外一个问题:字段的内联初始化是在哪里初始化的(这里的内联是指声明字段时同时进行初始化赋值,比如public int i = 1,而不是public in i),在《.NET框架程序设计》9.1节实例构造器中有解释,这里我只说结果,就是内联初始化实际上是在类型的构造器中完成的。那么这样看来,初始化B类对象b跟C中的Console.WriteLine()方法都发生在C类的构造器中,其实调用父类A的构造器也发生在C的构造器,至于为什么非要把内联初始化字段放在最前面,我就不清楚了,还请大家指点(可能有什么先搞定字段,再搞方法的规则吧,哈哈)。不过这个顺序是没错的,有IL作证:

 1.method public hidebysig specialname rtspecialname 
 2        instance void  .ctor() cil managed
 3{
 4  // 代码大小       28 (0x1c)
 5  .maxstack  2
 6  IL_0000:  ldarg.0
 7  IL_0001:  newobj     instance void B::.ctor()
 8  IL_0006:  stfld      class B C::b
 9  IL_000b:  ldarg.0
10  IL_000c:  call       instance void A::.ctor()
11  IL_0011:  ldstr      "C"
12  IL_0016:  call       void [mscorlib]System.Console::WriteLine(string)
13  IL_001b:  ret
14} // end of method C::.ctor

以上是C构造函数的IL代码,我们可以清楚地看到首先创建可B的实例b,当然同时调用了B的构造函数,然后把b值存为C的对象的一个字段,然后调用A的构造函数,然后在调用WriteLine方法。

可能会有人对B b = new B()是内联初始化不太理解,那么我再添加以行代码int i = 1;到后面,使C类变为:

class C : A
{
    public C()
    {
        Console.WriteLine("C");
    }
    B b = new B();
    int i = 1;
}

那么IL就变成:

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // 代码大小       35 (0x23)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  newobj     instance void B::.ctor()
  IL_0006:  stfld      class B C::b
  IL_000b:  ldarg.0
  IL_000c:  ldc.i4.1
  IL_000d:  stfld      int32 C::i
  IL_0012:  ldarg.0
  IL_0013:  call       instance void A::.ctor()
  IL_0018:  ldstr      "C"
  IL_001d:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0022:  ret
} // end of method C::.ctor

你看,这回比较清楚了吧,字段的初始化是在前面,同时说明了一个问题,就是,要避免内联初始化字段,这样会增加代码尺寸,把初始化放构造器中去进行, 这里不再细述。

转载于:https://www.cnblogs.com/wdxinren/archive/2005/05/17/157013.html

由一个Quiz想到的相关推荐

  1. C++中const——由一个例子想到的

    前天同学实现了<C++ Primer>中关于虚函数的一个例子,拿过来问我,代码如下: #include<iostream> #include<string> usi ...

  2. 你真的会用Android的Dialog吗?由一个Exception想到的

    一个Bug 前几日出现这样一个Bug是一个RuntimeException,详细信息是这样子的: java.lang.IllegalArgumentException: View not attach ...

  3. 从一个广告词想到的(转贴)高度决定视野,角度改变观念,尺度把握人

    来自Asp.net精英论坛:bbs.1aspx.com 打开电视,一句话语响彻入耳:".感觉很好,不由自主的在脑海中默默地重复了一遍,把它植入了记忆.随即的回读,觉得很富有哲理!如此简练.精 ...

  4. 一个很有借鉴价值的编程故事(转)

    英文原文:A Cautionary Tale of Learning to Code 这是一个真实的故事,关于我自己的.一个理智的生命个体是怎么一步步走向疯狂? 我穿着西装,坐在办公室里,脑子里有一个 ...

  5. 【Python教程】十四、找不到对象?用Python自己写一个|类与对象(二)

    更多教程请私信~ 来源:思路实验室 作者:室长 大家好,欢迎收看思路实验室出品的Python入门教程,我是室长. 书接上文,我们面对动物园甲方爸爸的要求有了一定的思路,它可以是这样的: 动物园所有的哺 ...

  6. 极简投资笔记-做一个富有的你自己

    微信公众号:北风中独行的蜗牛 关注可了解更多的内容.有问题或建议,请公众号留言; 何以解忧,唯有暴富! 暴富存在么,是的存在!但是我们要记住两点,第一暴富肯定是存在的,第二暴富的那个人一定不是你!,但 ...

  7. 一个资深Java架构师告诉你我们是如何将一个项目做烂的

    首先我想声明一个项目做烂不是你一个人挖坑就行的,这是一个很大的工程 需要团队协作 既然标题都用到了"烂"这个词,那什么才是烂呢? 在你的项目里,"烂"和&quo ...

  8. 【Java进阶营】一个资深Java架构师告诉你我们是如何将一个项目做烂的

    首先我想声明一个项目做烂不是你一个人挖坑就行的,这是一个很大的工程 需要团队协作 既然标题都用到了"烂"这个词,那什么才是烂呢? 在你的项目里,"烂"和&quo ...

  9. 如何编写可测试的golang代码

    每次在开发之前,我都会考虑写好单元测试,但是随着开发的进行,就会发现事情没有这么简单,因为更多时候项目中间夹杂着很多的数据库操作,网络操作,文件操作等等,每次涉及到有这些操作的单元测试,都要花费很大的 ...

最新文章

  1. 乐山市计算机学校坑不坑,据说这个学校很乱。
  2. android线程栈默认大小,线程的默认最大堆栈大小 - Internet Information Services | Microsoft Docs...
  3. mysql5.7.25数据库安装
  4. WHAT IS ERP
  5. c# websocket 心跳重连_websocket的简单使用
  6. MATLAB中median函数的用法
  7. 338. 比特位计数 golang
  8. android 4.2 camera gallery2,Android Gallery2 修改双击、手势放大的最大倍数
  9. android so导致启动慢,谈谈Android NDK中动态链接库(.so文件)的优化
  10. sublime_text_2 注册
  11. Android Camera数据流分析全程记录(overlay方式一)
  12. 关于前端浏览器 IE6bug 解决方案
  13. RHEL 5基础篇—Linux常用命令参考手册
  14. Java 基础知识 【钢镚核恒】
  15. java实现pdf转word
  16. cytoscape插件下载_Cytoscape软件下载
  17. Leetcode-数据结构-1.两数之和
  18. FTP之PASV与PORT
  19. Python100行-贪吃蛇小游戏
  20. 分步傅里叶算法_分布快速傅里叶算法,split-step fast fourier transformed,音标,读音,翻译,英文例句,英语词典...

热门文章

  1. linux退出远程登录命令,【linux命令】Linux 如何查看和关闭 ssh pts/n 远程登录用户...
  2. java专业编码_java编码中的坑(记一次解决编码BUG的经历) - 贪吃蛇学院-专业IT技术平台...
  3. Git错误:fatal: Not a git repository (or any of the parent directories)解决方法
  4. 堆(heap)与栈(stack)的区别(二)
  5. C++实现树的建立,查找,遍历输出
  6. 在VMware Workstation中安装Ubuntu设置网络连接
  7. leetcode算法第5题
  8. 两个摄像头是如何将照片拼接在一起的
  9. ENAS加载自己的数据集之路
  10. JVM最佳学习笔记一---Java内存区域与内存溢出异常