Java和C#的构造函数执行顺序及其对代码移植的实际影响

Java和C#的构造函数执行顺序及其对代码移植的实际影响,java,c#,constructor,Java,C#,Constructor,在这个问题上,主要答覆提到: 请注意,在Java中,基类是在运行变量初始值设定项之前初始化的。如果您曾经移植过任何代码,这是一个需要了解的重要区别 我想知道,有没有真正的例子因为这个问题而不能简单地在C#构造函数和Java构造函数之间进行移植 如果是这样的话,这些示例是否只是故意设计的反模式,或者它们是否存在于像某些开源项目这样的实际项目中 更新:我们能否列出不能简单移植的模式,例如,证明如果代码中没有这样的模式,那么可以使用工具简单地映射构造函数 我的尝试(在@John的帮助下):根据对该答案

在这个问题上,主要答覆提到:

请注意,在Java中,基类是在运行变量初始值设定项之前初始化的。如果您曾经移植过任何代码,这是一个需要了解的重要区别

我想知道,有没有真正的例子因为这个问题而不能简单地在C#构造函数和Java构造函数之间进行移植

如果是这样的话,这些示例是否只是故意设计的反模式,或者它们是否存在于像某些开源项目这样的实际项目中

更新:我们能否列出不能简单移植的模式,例如,证明如果代码中没有这样的模式,那么可以使用工具简单地映射构造函数

我的尝试(在@John的帮助下):根据对该答案的评论,下面的代码不能简单地移植,但它是经过精心设计的:

C#:

爪哇:


在您链接到的答案中,Jon Skeet提供了一个指向“”的链接,他在其中使用了以下示例:

public class MyBaseClass
{
    public MyBaseClass ()
    {
        Console.WriteLine (this.ToString());
    }
}

public class MyDerivedClass : MyBaseClass
{
    string name="hello";
    
    public MyDerivedClass() : base()
    {
        Console.WriteLine (this.ToString());
    }

    public override string ToString()
    {
        return name;
    }
}
在C#中创建MyDerivedClass的新实例时,输出为:

hello
hello
第一行是hello,因为name变量的实例变量初始值设定项直接在基类构造函数之前运行。Java语法中的等效代码将输出:

null
hello 

我不认为这个例子是特别设计的:在基类中调用一个虚拟方法(如<>代码> toStRew()/代码>),也不是虚拟方法会尝试使用一个成员变量,这是不可想象的。事实上,考虑到Jon已经用两种语言编写了库及其端口,假设Jon个人可能会遇到这种情况并不牵强

但是,正如他提到的:

这是一个非常糟糕的想法-只要可能,只从构造函数调用非虚拟方法,如果您绝对必须调用虚拟方法,请非常仔细地记录它是从构造函数调用的,以便希望重写它的人知道,在调用它时,他们的对象可能不处于一致状态(因为他们自己的构造函数还没有运行)

所以反模式:是的。是故意设计的?也许不是。

如果你想把它添加到你的问题中,我做了一个测试。但是是的,我观察到了相同的行为-
str
为空。
hello
hello
null
hello