所以,对象初始化器是各种方便的 - 特别是如果你正在做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() { ...
它甚至没有名称来引用它!
我该如何解决这个问题?我可以简单地使用对象初始化器来制作嵌套引用吗?
答案 0 :(得分:7)
我可以简单地使用对象初始化器来制作嵌套引用吗?
你是对的 - 你做不到。会有一个循环; 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() };
答案 1 :(得分:2)
使用对象初始化器无法做到这一点。但是,你可以使用propery代码来实现这个技巧:
class A
{
B b;
public B B
{
set
{
b = value;
b.a = this;
}
get
{
return b;
}
}
}
class B
{
public A a;
}
致电:
var a = new A { B = new B() };
答案 2 :(得分:1)
此问题并非特定于对象初始值设定项,它是C#语言的一般限制。在明确分配之前,您不能使用局部变量。这是一个更简单的复制品
Class1 Foo(Class1 c1) {
return c1;
}
void Example() {
Class1 c1 = Foo(c1);
}
答案 3 :(得分:1)
我认为无论如何都要解决这个问题,当应用程序实例化Class1对象时,它需要首先创建Class2对象,以便它知道引用所在的内存位置。如果您尝试以下操作,可以看到这一点:
Class1 myClass1 = null;
myClass1 = new Class1()
{
instance = new Class2
{
parent = myClass1
}
};
这将编译并运行,但Class2的parent属性将为null,因为这是代码内部行运行时的值,这意味着最内部的行是第一个被执行的行。 / p>
答案 4 :(得分:0)
你当然可以使用嵌套对象初始化器,我一直这样做。
但是,在您的特定情况下,您的对象具有循环引用。您需要在将其分配给另一个之前完成实例化。否则,您正在为编译器处理一个它无法处理的经典chicken and egg problem。
答案 5 :(得分:0)
你的例子没有反映出好的班级设计,IMO;这是不恰当的凝聚力,并创建一个循环引用。这就是不可能在一个表达式中将它们一起实例化的原因。
我建议你回到绘图板并将你的课程重构为父/子关系。我在子类上使用构造函数注入,并让子进程告诉父进程它是它的子进程。
例如:
public class ParentClass
{
public List<ChildClass> 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 实例? - Andy Hohorst
然后你必须提前知道父类。
var parent = new ParentClass();
var child = new ChildClass(parent);
或
var parent = new ParentClass();
// qry, etc.
select new ChildClass(parent)