C#结构文档:构造函数初始值设定项与`ref`和`out`参数的关系
c#
在 C# 文档和特别的结构中,我发现了这些我无法理解的句子:
如果 struct 实例构造函数没有指定构造函数初始化器,则 this 变量对应一个 struct 类型的 out 参数,与 out 参数类似,在构造函数返回的每个位置都必须明确赋值(Definite assignment)。如果 struct 实例构造函数指定了构造函数初始化器,则 this 变量对应于 struct 类型的 ref 参数,并且类似于 ref 参数, this 被认为是在构造函数主体的入口处明确赋值的。
我想知道构造函数中的 this 关键字与 ref 和 out 关键字之间的关系是什么。
回答
如果您不熟悉文档中使用的术语,这可能看起来有点令人费解,但让我们一步一步来。
基本规则是:结构构造函数必须确保结构实例的所有字段都已初始化。没有例外。
此外,与以下相关的是“构造函数初始值设定项”意味着您通过多个构造函数链接调用:
public YourStruct(...) : this(...)
^----+----^
|
+-- constructor initializer
供参考out和ref方法参数:
public void Test(out int x) { ... }
public void Test(ref int x) { ... }
意味着out int x参数必须在方法中完全初始化,并且在方法开始时被认为是未分配的。请参阅输出参数修饰符文档以供参考。
而ref int x参数被认为是在方法开始时分配的,方法可以更改它但不是必须的。有关更多信息,请参阅ref 关键字。
所以,让我们现在看看其余的文档。
如果您的构造函数没有构造函数初始值设定项,则意味着您的构造函数必须自己解决基本规则。这意味着它类似于out方法的参数,您的构造函数必须在返回之前完全初始化 struct 实例。
但是,如果您确实有构造函数初始值设定项,那么该构造函数还必须完全初始化 struct 实例,因此当您的构造函数开始执行时,该实例已经完全初始化。在这种情况下,您的构造函数不必再初始化所有字段,而是可以有选择地仅更改它需要的字段。这就是ref参数的含义。
让我举个例子吧:
public struct X
{
public int A;
public int B;
public X(int a, int b)
{
// no constructor initializer, MUST initialize both A and B
A = a;
B = b;
}
}
然而:
public struct X
{
public int A;
public int B;
public X(int a)
: this(a, 0)
{
// constructor initializer, DOES NOT have to initialize anything
// you can, though, if you want to change B
B++;
}
public X(int a, int b)
{
// no constructor initializer, MUST initialize both A and B
A = a;
B = b;
}
}
所以基本上文档说明:
- 如果你没有一个构造函数初始化,构造有完全初始化的
this变量,类似于如何的out参数工作 - 如果您确实有构造函数初始值设定项,则构造函数不必执行任何操作,您可以将
this变量视为类似于ref参数。