首页 >后端开发 >C++ >为什么括号在某些 C# 对象初始化器中是可选的,但在其他对象初始化器中是必需的?

为什么括号在某些 C# 对象初始化器中是可选的,但在其他对象初始化器中是必需的?

Mary-Kate Olsen
Mary-Kate Olsen原创
2025-01-15 13:37:43703浏览

Why Are Parentheses Optional in Some C# Object Initializers but Required in Others?

C# 对象初始化器构造函数中括号的可选性:原因及歧义消除

在 C# 3.0 中,如果存在无参数构造函数,则对象初始化器构造函数允许省略括号。此功能的添加基于以下几个因素:

  • 简化设计、规范和开发过程,降低工作量。
  • 消除冗余,因为当使用对象初始化器进行属性赋值时,参数列表通常不存在。
  • 维护负担低,因为此功能自实现以来未出现任何已知的错误。

默认构造函数调用中括号的缺失

然而,在没有对象初始化器的对象创建表达式中,默认构造函数调用中的括号仍然是必需的。此限制是为了避免歧义。例如,在以下代码中:

<code class="language-csharp">class P
{
    class B
    {
        public class M { }
    }
    class C : B
    {
        new public void M(){}
    }
    static void Main()
    {
        new C().M(); // 1
        new C.M();   // 2
    }
}</code>

第 1 行创建一个新的 C 对象,调用其默认构造函数,并在新对象上调用 M 实例方法。第 2 行创建一个 B.M 的实例并触发其默认构造函数。如果第 1 行的括号是可选的,则第 2 行将产生歧义,因为它也可以指 C.M。

歧义检测方法

确定 C# 功能中的歧义涉及几种方法:

  • 手动检查和分析语法和语义。
  • 正式证明,通常由外部研究团队进行。
  • 使用解析器生成器进行机器分析以搜索潜在的歧义。

潜在歧义的示例

考虑添加一个新的前缀运算符“frob”:

<code class="language-csharp">x = frob 123 + 456;</code>

这可以解释为对 123 456 的结果执行 frob 运算,或者将 10 赋值给名为 x 的 frob 类型变量。

在另一个示例中,C# 2.0 中的以下表达式是模棱两可的:

<code class="language-csharp">yield(x);</code>

它可以表示在迭代器中产生 x,也可以表示使用 x 作为参数调用 yield 方法。通过将其修改为“yield return(x)”,消除了歧义。

以上是为什么括号在某些 C# 对象初始化器中是可选的,但在其他对象初始化器中是必需的?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn