C#对象初始值设定项的嵌套使用
因此,对象初始值设定项非常方便——特别是如果你在做linq,它们是绝对必要的——但我不太明白这一点:C#对象初始值设定项的嵌套使用,c#,c#-3.0,C#,C# 3.0,因此,对象初始值设定项非常方便——特别是如果你在做linq,它们是绝对必要的——但我不太明白这一点: public class Class1 { public Class2 instance; } public class Class2 { public Class1 parent; } 这样使用: Class1 class1 = new Class1(); class1.instance = new Class2(); class1.parent = class1; 作为初始
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() { ...
它甚至连一个名字都没有
我该怎么做?我可以不使用对象初始值设定项进行嵌套引用吗?这个问题不是对象初始值设定项特有的,它是C语言中的一般限制。在明确指定局部变量之前,不能使用它。这里有一个更简单的程序
Class1 Foo(Class1 c1) {
return c1;
}
void Example() {
Class1 c1 = Foo(c1);
}
我可以不使用对象初始值设定项进行嵌套引用吗
你是对的,你不能。会有一个循环;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() };
我认为无论如何都没有办法解决这个问题,当应用程序实例化Class1对象时,它需要先创建Class2对象,以便知道引用在内存中的位置。如果尝试以下操作,您可以看到这一点:
Class1 myClass1 = null;
myClass1 = new Class1()
{
instance = new Class2
{
parent = myClass1
}
};
这将编译并运行,但Class2的父属性将为null,因为这是代码内行运行时的值,这意味着最内行是第一个要执行的行。您当然可以使用嵌套对象初始值设定项,我一直都这样做
但是,在特定情况下,对象具有循环引用。在将一个实例分配给另一个实例之前,需要完成它的实例化。否则,您将给编译器一个它无法处理的经典 对象初始值设定项不能这样做。但是,您可以使用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() };
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);
}
}
是的,这在LINQ是有效的:
// qry, etc.
select new ChildClass(new ParentClass()).Parent
但是我怎么才能把所有的 子类具有相同的父类 实例?–安迪·霍霍斯特 那么您必须提前知道父类
var parent = new ParentClass();
var child = new ChildClass(parent);
或
但是,我如何使所有的子类都具有相同的父类实例呢?这不是鸡和蛋的问题,至少不是我如何理解初始值设定项的问题:只是声明一个对象并设置其属性的语法糖。对不起,根据对对象初始值设定项的解释,它“不应该”是一个。创建第一个对象,然后为其参数指定值。因为我可以用对象初始化器应该编译到的风格来做这件事,所以我应该可以用对象初始化器来做。我最喜欢这个答案,但它不适合我,因为我忽略了类2实际上是列表,以便让示例更清楚。糟了,结果适得其反。
var parent = new ParentClass();
var child = new ChildClass(parent);
var parent = new ParentClass();
// qry, etc.
select new ChildClass(parent)