嵌套使用C#Object Initializers

所以,对象初始化器是各种方便的 – 特别是如果你正在做linq,它们是完全必要的 – 但我不能完全弄明白这个:

public class Class1 { public Class2 instance; } public class Class2 { public Class1 parent; } 

使用这样的:

 Class1 class1 = new Class1(); class1.instance = new Class2(); class1.parent = class1; 

作为初始化者:

 Class1 class1 = new Class1() { instance = new Class2() { parent = class1 } }; 

这不起作用,class1应该是一个未分配的局部变量。 当你做类似的事情时,它在Linq变得更加棘手

 select new Class1() { ... 

它甚至没有名称来引用它!

我该如何解决这个问题? 我可以简单地使用对象初始化器来制作嵌套引用吗?

我可以简单地使用对象初始化器来制作嵌套引用吗?

你是对的 – 你做不到。 会有一个循环; A要求B进行初始化,但B要求A。 确切地说 – 您当然可以创建嵌套对象初始化器,但不能使用循环依赖项。

但你可以 – 我建议你应该尽可能 – 按照以下方式解决这个问题。

 public class A { public B Child { get { return this.child; } set { if (this.child != value) { this.child = value; this.child.Parent = this; } } } private B child = null; } public class B { public A Parent { get { return this.parent; } set { if (this.parent != value) { this.parent = value; this.parent.Child = this; } } } private A parent = null; } 

在属性中构建关系有一个好处,如果您忘记了其中一个初始化语句,则无法获得不一致的状态。 很明显,这是一个次优的解决方案,因为你需要两个语句来完成一件事。

 b.Parent = a; a.Child = b; 

使用属性中的逻辑,您只需使用一个语句即可完成任务。

 a.Child = b; 

或者反过来说。

 b.Parent = a; 

最后使用对象初始化器语法。

 A a = new A { Child = new B() }; 

你不能用Object Initializers做到这一点。 但是,你可以使用propery代码来做到这一点:

 class A { B b; public BB { set { b = value; ba = this; } get { return b; } } } class B { public A a; } 

打电话给:

 var a = new A { B = new B() }; 

此问题并非特定于对象初始值设定项,它是C#语言中的一般限制。 在明确分配之前,您不能使用局部变量。 这是一个更简单的复制品

 Class1 Foo(Class1 c1) { return c1; } void Example() { Class1 c1 = Foo(c1); } 

我认为无论如何都没有解决这个问题,当应用程序实例化Class1对象时,它需要首先创建Class2对象,以便它知道引用所在的内存位置。 如果您尝试以下操作,可以看到此内容:

  Class1 myClass1 = null; myClass1 = new Class1() { instance = new Class2 { parent = myClass1 } }; 

这将编译并运行,但Class2的parent属性将为null,因为这是代码内部行运行时的值,这意味着最内部的行是第一个执行的行。

你当然可以使用嵌套对象初始化器,我一直这样做。

但是,在您的特定情况下,您的对象具有循环引用。 您需要在将其分配给另一个之前完成实例化。 否则,你正在给编译器处理一个它无法处理的经典鸡和蛋问题 。

你的例子没有反映出良好的class级设计,IMO; 这是不恰当的凝聚力,并创建一个循环引用。 这就是不可能在一个表达式中将它们一起实例化的原因。

我建议你回到绘图板并将你的课程重构为父/子关系。 我在子类上使用构造函数注入,并让子进程告诉父进程它是它的子进程。

例如:

 public class ParentClass { public List Children; public void AddChild(ChildClass child) { Children.Add(child); // or something else, etc. } // various stuff like making sure Children actually exists before AddChild is called } public class ChildClass { public ParentClass Parent; public ChildClass(ParentClass parent) { Parent = parent; Parent.AddChild(this); } } 

然后,在您的调用代码中:

 var parent = new ChildClass(new ParentClass()).Parent; 

并且,是的,这在LINQ中有效:

 // qry, etc. select new ChildClass(new ParentClass()).Parent 

但是,如何使所有ChildClass具有相同的ParentClass实例? – 安迪霍斯特

然后你必须提前知道父类。

 var parent = new ParentClass(); var child = new ChildClass(parent); 

要么

 var parent = new ParentClass(); // qry, etc. select new ChildClass(parent)