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

推荐订阅源

T
The Blog of Author Tim Ferriss
S
Securelist
D
Docker
The Register - Security
The Register - Security
GbyAI
GbyAI
Recorded Future
Recorded Future
Engineering at Meta
Engineering at Meta
Stack Overflow Blog
Stack Overflow Blog
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
罗磊的独立博客
博客园 - 【当耐特】
F
Full Disclosure
WordPress大学
WordPress大学
腾讯CDC
小众软件
小众软件
大猫的无限游戏
大猫的无限游戏
D
DataBreaches.Net
SecWiki News
SecWiki News
L
Lohrmann on Cybersecurity
I
InfoQ
MyScale Blog
MyScale Blog
量子位
Cyberwarzone
Cyberwarzone
博客园 - 三生石上(FineUI控件)
The Hacker News
The Hacker News
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Jina AI
Jina AI
博客园_首页
H
Help Net Security
K
Kaspersky official blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Webroot Blog
Webroot Blog
Blog — PlanetScale
Blog — PlanetScale
V
Vulnerabilities – Threatpost
Y
Y Combinator Blog
The Cloudflare Blog
P
Proofpoint News Feed
V
Visual Studio Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tailwind CSS Blog
爱范儿
爱范儿
P
Privacy International News Feed
Security Archives - TechRepublic
Security Archives - TechRepublic
The GitHub Blog
The GitHub Blog
C
Cybersecurity and Infrastructure Security Agency CISA
B
Blog RSS Feed

博客园 - 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