惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
I
InfoQ
雷峰网
雷峰网
Hugging Face - Blog
Hugging Face - Blog
IT之家
IT之家
云风的 BLOG
云风的 BLOG
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
MyScale Blog
MyScale Blog
The GitHub Blog
The GitHub Blog
博客园_首页
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
G
Google Developers Blog
WordPress大学
WordPress大学
B
Blog
人人都是产品经理
人人都是产品经理
小众软件
小众软件
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
量子位
Apple Machine Learning Research
Apple Machine Learning Research
N
Netflix TechBlog - Medium
Last Week in AI
Last Week in AI
博客园 - 聂微东
Jina AI
Jina AI

博客园 - Let's DotNet

Generating SSH Keys for Git Keyboard shortcuts for Windows Office 2007安装后Google拼音输入法莫名其妙消失了,换成了微软拼音 在装有SAP客户端后安装VS2003时出错 Difference between ICallbackEventHandler and AJAX 无法通过Project Professional 2003连接到Project Server 2003的解决办法(转) AutoCoder——全新自动代码框架 基于性能的编程技巧点滴 "Union" in Oracle - Let's DotNet Atlas Project (转) DB2编程技巧 动态添加控件的一个注意点 SQL Server 高阶应用 限制多行文本框(TextArea)中输入文字的长度(转) 给自己的某个文件夹的文件做一个列表(转) Google 桌面搜索... Eclipse 3.0资料收集(转) 一种改进的轻量级.NET应用程序性能测试框架 ASP.NET 应用程序性能优化
C# 类初始化顺序 - Let's DotNet
Let's DotNet · 2009-02-15 · via 博客园 - Let's DotNet

 看起来这是一个不太容易不被注意的一个问题,

using System;

class Foo
{
    public Foo(string s)
    {
        Console.WriteLine("Foo constructor: {0}", s);
    }
    public void Bar() { }
}
class Base
{
    readonly Foo baseFoo = new Foo("Base initializer");
    public Base()
    {
        Console.WriteLine("Base constructor");
    }
}
class Derived : Base
{
    readonly Foo derivedFoo = new Foo("Derived initializer");
    public Derived()
    {
        Console.WriteLine("Derived constructor");
    }
}
static class Program
{
    static void Main()
    {
        new Derived();
    }
}

 这段代码的实际输出是:

Foo constructor: Derived initializer
Foo constructor: Base initializer
Base constructor
Derived constructor

我觉得关键的注意点是,C#类需要确保类型(Type)正确性(避免有NULL),所以总是在一个类正式初始化之前进行成员的初始化,接下来的动作依次类推并递归。下面是比较合理的解释,

Process of creating an Instance of a Class goes in the following order: (static would be different)

Step 1) Compiler executes code related to instance variable declarations; this is to identify the fields required to construct the instance.

Step 2) Compiler executes the desired constructor - Constructor is the first method that is called on an instance.

Trick is here: To construct a Derived class instance a base class instance needs to be constructed.

Let’s get back to the code we are looking at:

1) Line 'new Derived();' of the 'static void Main()' method creates an instance of 'Derived' class. So the compiler should run Step 1 on 'Derived' class.

Result: 'Foo constructor: Derived initializer' is written to the console.

2) Compiler should run Step 2 on 'Derived' class. To create an instance of the derived class it first needs to construct the base class instance. Hence,

i) Step 1 is called on 'Base' class.

Result: 'Foo constructor: Base initializer' is written to the console.

ii) After Step 1, Step 2 is called on 'Base' class.

Result: 'Base constructor' is written to the console.

Since the Base class instance is constructed, it finishes with constructing the Derived class by calling Step 2 on the 'Derived' class

Result: 'Derived constructor' is written to the console.

 而在第二篇( http://blogs.msdn.com/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-opposite-order-as-constructors-part-two.aspx)中,更是有详细的例子解释说明如果不这样做的问题。(当然它来自不良的变成习惯)。

 对此C#初始顺序的解释(我想同样适合于Java),引起了很多C++用户的再次的“笑”评。其实,个中原因还是托管型语言希望拥有更稳定的解释执行环境,强调了“类型安全和检查”的方针执行,所以不能说谁好谁差。

 不过,倒是提醒我们在没有特殊的情况下,不要在构造函数外初始化成员变量,也许是一个好的习惯。

 原文:Why Do Initializers Run In The Opposite Order As Constructors

 http://blogs.msdn.com/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one.aspx

 http://blogs.msdn.com/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-opposite-order-as-constructors-part-two.aspx