【问题标题】:Initializer syntax初始化器语法
【发布时间】:2010-01-07 12:17:06
【问题描述】:

我喜欢 C# 3 initializer syntax 并经常使用它,但是今天在查看 Reflector 时,出现了以下问题:

var binding = new WSHttpBinding
{
  ReaderQuotas = { MaxArrayLength = 100000 },
  MaxReceivedMessageSize = 10485760
};

一开始我以为是个错误,但它确实编译了!猜猜我一直在学习新东西。 :)

据我所知,它设置了ReaderQuotasWSHttpBinding 属性的MaxArrayLength 属性。

这个语法是创建一个新的ReaderQuotas 对象然后设置属性,还是假设属性已经初始化?这是初始化“子”属性的一般方法吗?

我确实觉得语法有点混乱......

【问题讨论】:

  • 您可能对this post 感兴趣,它讨论了此类初始化程序的语义和用例

标签: c# .net object-initializers


【解决方案1】:

不,除非您使用= new SomeType {...},否则不会创建新对象:

var binding = new WSHttpBinding
{
    ReaderQuotas = new XmlDictionaryReaderQuotas { MaxArrayLength = 100000 },
    MaxReceivedMessageSize = 10485760
};

您的示例显示了用于设置 现有 子对象属性的初始化程序语法。在集合上调用“添加”方法也有类似的语法。

您的代码大致可与:

var binding = new WSHttpBinding();
binding.ReaderQuotas.MaxArrayLength = 100000;
binding.MaxReceivedMessageSize = 10485760;

【讨论】:

  • 看起来和那个一样,除了句法上的区别吗?看起来好像(除非 ReaderQuotas 在 WSHttpBinding 的构造函数中初始化)它应该抛出异常
  • 谢谢,这让我大吃一惊 :) 我假设“添加”是指集合初始化程序?
  • @james:我希望在这种情况下会出现异常,但是如果您不知道构造函数中做了什么,那么没有源代码可能会令人困惑。一些构造函数重载可能会或可能不会初始化该属性,这将导致更多的混乱。
  • 不值得一个额外的答案 - 但这在 C# 的第 8 章中进行了深入讨论。本章第一版可从manning.com/skeet免费获取
  • 詹姆斯,差别很微妙。虽然代码在语义上等价,但我们实际上生成了“temp = new Binding(); blah blah blah; var binding = temp;”为什么?因为变量“绑定”不能在它自己的初始化器中使用!这将是一个鸡与蛋的问题。如果我们完全按照 Marc 的建议生成代码,那么“绑定”将在在初始化程序代码运行之前被初始化,并且有人可能会在其部分初始化的状态下观察到“绑定”。
【解决方案2】:

这有点令人困惑,我同意。

您应该阅读第 7.6.10.2 节 规范;这一切都解释了 那里。例如:

一个成员初始化器,指定 等号后的表达式 处理方式与 分配给字段或属性。

一个成员初始化器,它指定一个 等号之后的对象初始化器 sign 是一个嵌套的对象初始化器, 即嵌入式的初始化 目的。而不是分配一个新的 字段或属性的值, 嵌套对象中的赋值 初始化器被视为赋值 给字段或属性的成员。 嵌套对象初始化器不能 应用于具有值的属性 类型,或只读字段 值类型。

一个成员初始化器,它指定一个 集合初始化器之后 等号是一个初始化 嵌入式集合。代替 将新集合分配给 字段或属性,给定的元素 在初始化程序中被添加到 字段引用的集合或 属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 2010-09-27
    • 1970-01-01
    • 2019-04-01
    • 2017-11-05
    相关资源
    最近更新 更多