C# 结构文档:构造函数初始化器与 `ref` 和 `out` 参数的关系

Posted

技术标签:

【中文标题】C# 结构文档:构造函数初始化器与 `ref` 和 `out` 参数的关系【英文标题】:C# structs documentation: relation of contructor initializers to `ref` and `out` parameters 【发布时间】:2021-09-21 13:36:19 【问题描述】:

在 C# 文档和特别是 Structs 中,我发现了这些我无法理解的句子

如果struct实例构造函数没有指定构造函数初始化器,this变量对应struct类型的一个out参数,和out参数类似,this必须在每个位置明确赋值(Definite assignment)构造函数返回。如果 struct 实例构造函数指定了构造函数初始化器,则 this 变量对应 struct 类型的 ref 参数,与 ref 参数类似,this 被认为是在构造函数体的入口处确定分配的。

我想知道构造函数中的 this 关键字与 ref 和 out 关键字之间的关系。

【问题讨论】:

【参考方案1】:

如果您不熟悉 documentation 中使用的术语,这可能看起来有点复杂,但让我们一步一步来。

基本规则是:结构构造函数必须确保结构实例的所有字段都已初始化。没有例外。

此外,与以下内容相关的是“构造函数初始化器”意味着您通过多个构造函数链接调用:

public YourStruct(...) : this(...)
                       ^----+----^
                            |
                            +-- constructor initializer

作为参考,outref 方法的参数:

public void Test(out int x)  ... 
public void Test(ref int x)  ... 

意味着out int x 参数必须在方法中完全初始化,并且在方法开始时被认为是未分配的。参考out parameter modifier documentation。

ref int x 参数被认为是在方法开始时分配的,方法可以更改它,但不是必须的。请参阅ref keyword 了解更多信息。

那么,让我们现在就来看看剩下的文档吧。

如果你没有为你的构造函数提供构造函数初始化器,那么这意味着你的构造函数必须自己处理基本规则。这就是它类似于方法的out 参数的含义,您的构造函数必须在返回之前完全初始化结构实例。

然而,如果你确实有一个构造器初始化器,那么那个构造器必须完全初始化结构实例,所以到那时你的构造函数开始执行,实例已经完全初始化。在这种情况下,您的构造函数不再需要初始化所有字段,而是可以选择性地只更改它需要的字段。这就是 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 参数的工作方式 如果您确实有构造函数初始化程序,则构造函数不必做任何事情,您可以考虑使用类似于ref 参数的this 变量。

【讨论】:

非常好的答案,但我认为如果你能在开头简要解释或链接到refout参数的含义会有所帮助。 哇,非常感谢,这是一个很棒的很棒的有用的答案。我喜欢它。 @Lasse V.karlsen

以上是关于C# 结构文档:构造函数初始化器与 `ref` 和 `out` 参数的关系的主要内容,如果未能解决你的问题,请参考以下文章

c#面试问题及答案

[Unity] C#中级编程 - 04 - 泛型/构造函数/ref

C# 结构体

C# 构造函数总结

C# 构造函数总结

对象初始化器与集合初初始化器