为什么不能在成员初始化器中使用 'this'?

56

可能是重复问题:
成员初始化程序中不能使用'this'关键字?

有人知道为什么如果我尝试这样做会出现错误:

public class Bar
{
    public Bar(Foo foo)
    {
    }
}

public class Foo
{
    private Bar _bar = new Bar(this);
}

我遇到一个错误:

"无法在成员初始化程序中使用 'this'"

但以下代码可以正常工作:

public class Foo
{
    private Bar _bar;

    public Foo()
    {
        _bar = new Bar(this);
    }
}

有人知道这背后的原因吗?我理解它们将编译为相同的IL,因此很好奇为什么允许使用其中一个而不允许使用另一个。

谢谢, Alex


2
我不确定为什么这个问题被关闭为重复,因为另一个问题的答案是关于为什么它没有被报告为错误的答案是“这是编译器中的一个错误”,而没有真正解释为什么它不被允许。 - Powerlord
5个回答

56
我怀疑这是为了防止你在基类构造函数运行之前使用对象,确保所有基类成员被适当初始化。(变量初始化程序在执行基类构造函数之前执行,而构造函数体在此之后执行。)
下次我靠近它时会检查注释规范是否有任何说明...
编辑: C# 4的注释规范没有任何解释。只有(在10.5.5.2中):
实例字段的变量初始值设定项不能引用正在创建的实例。

有趣,谢谢。从未意识到变量初始化器在基类构造函数之前运行... - AlexC
20
您说得没错。我们应该在下一版的注释规范中加入这一点,这是个好主意。 - Eric Lippert
1
这里有一个VS的建议,将我的后备字段转换为Lazy - tacos_tacos_tacos

15

字段初始化器在基类构造函数之前运行,因此 this 还不存在。只有在基础构造函数执行完成后,它才存在。

17.10.2 实例变量初始化器:

当一个实例构造函数没有构造函数初始化器,或者它有一个形如 base(...) 的构造函数初始化器时,该构造函数隐式执行由其类中声明的实例字段的变量初始化所指定的初始化。这对应于一系列分配,在进入构造函数并在直接基类构造函数的隐式调用之前立即执行。变量初始化器按照它们在类声明中出现的文本顺序执行。


1
它确实存在 - 只是还没有完全初始化。 - Jon Skeet

0

我相信这是因为字段在类初始化之前初始化,所以当运行以下代码时:

private Bar _bar = new Bar(this);

"

"this"没有实际值可供引用。

将它放在构造函数中意味着有一个可以被"this"引用的"Foo"实例。

"

0
在C#中,没有逻辑意图放在方法和属性的主体之外。
字段初始化器是一个例外,但有一些限制。
使用this关键字获取当前对象的引用是错误的,因为类字段声明不是逻辑,而是类设计,而this是运行时语义的一部分。
顺便说一下,这似乎是C#的设计决策,因为实际上,字段初始化器在类构造期间运行,所以"声明类的当前实例"应该通过this可用。但再次问一下,在方法或属性主体范围之外,this会是什么? 正如Jon Skeet和其他人指出的那样,this不可用,因为字段初始化器在基类构造函数执行后执行。

在方法或属性体外,它仍然是代码执行上下文中的对象。对于成员初始化器来说,允许这样做是完全有意义的 - 只是如果它尝试使用尚未由基类初始化的状态,则会出现问题。 - Jon Skeet
完全同意,感谢您的评论。这就是为什么我指出这是一个C#设计决策的原因,但我提出问题是因为我发现在这个范围内使用this关键字很容易出现错误。 - Matías Fidemraizer
请注意,通过对 C# 进行更改以使其更像 Java(在执行超类构造函数之前执行变量初始化器),可以消除错误的根本原因。我认为这 从根本上 是有意义的——只是有一些要注意的地方。 - Jon Skeet
@Jon Skeet。同意并感谢提供信息。事实上(也适用于我的情况),我会避免在代码中使用字段初始化器。而且,我只有在要设置只读字段时才会初始化字段。我更喜欢远离它们。对于设置私有字段,我使用属性设置器。 - Matías Fidemraizer

0

成员初始化程序在类构造函数之前运行。请考虑您可能在单个类中有许多成员初始化程序。

如果您在构造函数中使用'this' -> 所有具有初始化程序的成员都已初始化。所以一切都没问题。

如果您在成员初始化程序中使用'this':其他成员(附有初始化程序)可能尚未初始化 -> 'this'尚未准备好。这就是为什么不允许在此处使用'this'的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接