C#:通过内联对象实例化直接设置子类属性

C#:通过内联对象实例化直接设置子类属性,c#,object,inline,instantiation,C#,Object,Inline,Instantiation,我知道还有其他方法可以剥这只猫的皮,但我希望有人能帮助我理解为什么在C#中,当内联实例化“main”对象时,我不能直接设置子类属性 例如,如果我有以下课程: public class SubClass { public string SubField { get; set; } } public class MainClass { public string MainField { get; set; } public SubClass Sub { get; set; } p

我知道还有其他方法可以剥这只猫的皮,但我希望有人能帮助我理解为什么在C#中,当内联实例化“main”对象时,我不能直接设置子类属性

例如,如果我有以下课程:

public class SubClass
{
  public string SubField { get; set; }
}

public class MainClass
{
  public string MainField { get; set; }
  public SubClass Sub { get; set; }

  public MainClass()
  {
    Sub = new SubClass();
  }
}
如果尝试以下操作,则会出现错误:

var main = new MainClass
{
  MainField = "Main Value",
  Sub.SubField = "Sub Value"
};
我在“Sub.SubField=…”行中得到的错误是:

* "Invalid initializer member declarator"
* "The name 'Sub' does not exist in the current context"
当然,以下方法是有效的:

var main = new MainClass
{
  MainField = "Main Value",
  Sub = new SubClass { SubField = "Sub Value" }
};
但是,在我看来,它更麻烦,更不容易封装

我很困惑为什么C#不能识别声明的对象和/或它如何知道它没有被实例化。在其他情况下就不那么小心了


我肯定我错过了一个重要的概念。有人能启发我吗?提前谢谢

首先,这不是一个子类。它是一个单独的对象,作为属性公开

引用MS:对象初始值设定项允许您在创建时为对象的任何可访问字段或属性赋值,而无需显式调用构造函数


请参阅:

这将满足您的要求:

var main = new MainClass { 
  MainField = "Main Value", 
  Sub = { SubField = "Sub Value" } 
}; 
上述代码实际上是按照以下方式编译的:

var main = new MainClass(); 
main.MainField = "Main Value";
main.Sub.SubField = "SubValue";
我更喜欢对象初始化语法,因为它的噪音稍微小一些,而且因为大多数开发人员都习惯于使用C#块,所以他们更可能将所有东西都放在一起


另外,我建议使MainClass上的子属性具有私有可设置性。

您所尝试的是非法的,并且没有任何意义,因为
Sub
是一个新对象。你仍然可以实现你想要的(见安迪的答案)

请看第7.6.10.2节C#语言规范中的对象初始值设定项,其中规定:


对象初始值设定项由一系列成员初始值设定项组成,由{和}标记包围,并用逗号分隔。每个成员初始值设定项必须命名要初始化的对象的可访问字段或属性,后跟等号和表达式、对象初始值设定项或集合初始值设定项。对于同一字段或属性,对象初始值设定项包含多个成员初始值设定项是错误的。对象初始值设定项不可能引用它正在初始化的新创建的对象


最后一部分是关键。您正在创建一个新的MainClass实例,因此可以设置MainClass对象的属性。Sub是一个完全不同的对象,从MainClass内联构造函数设置它的属性是没有意义的。OP可以实现他想要的,Sub是一个完全不同的对象并不重要。否决,因为你的答案暗示这是不可能的。我没有暗示不可能使用初始值设定项初始化属性,我只是解释了为什么他试图做的不起作用。问题是,当他使用初始值设定项时,构造函数(他假设正在被调用)没有被调用。谢谢,@sonicthlichen,但是我通过调试完成了,构造函数被调用了。不幸的是,这对我的情况没有帮助。“对象初始值设定项不可能引用它正在初始化的新创建的对象。”这是我想要的澄清。我知道这一点,但我认为“子类”(呃,“子对象”)只是另一个属性。谢谢你,@Andy。这实现了我所说的(因为缺少一个更具信息性的词)“更好的封装”。不幸的是,它仍然比我希望的更麻烦,但多亏了“布莱恩·科斯比”(还有一点“SonicTheLichen”),我更好地理解了为什么我想做的事情行不通。(我想+1你,但这仍然比我的新手级别高。我想布莱恩提供了最接近的答案。)@jweekes我不确定我是否明白;虽然这个解决方案可能没有您希望的那么简洁,但它确实满足了我的要求。我已经更新了我的答案,以显示在不使用对象初始化的情况下需要做什么,我认为这比使用对象初始化更麻烦。在上面的语法中,它指的是新创建的子对象。@Andy我想要的是不必为子对象使用对象初始值设定项语法——不过我现在正在热身。您的解决方案与我在原始帖子中所说的相同,只是您巧妙地删除了“新的子类”。如果我不能按我想要的方式做,我想知道为什么不能。@jweekes啊,我现在明白了。我以为你们只是不能在子类上设置属性,我不知道你们真的打算替换它。