这种设置是否存在任何可能导致无限循环实例化的问题?
引用类型是null
默认的。除非您实例化一个新实例并将其分配给该变量,否则不会为该类型调用任何代码。
每个构造函数都构造另一个对象的实例吗?他们将来有可能(可能是意外)吗?如果是这样,那么是的,您可以点击您正在谈论的场景:
class A
{
public A()
{
this.B = new B();
}
public B B;
}
class B
{
public A A = new A(); // This is the same as instantiating the object in the ctor
}
// ...
A obj = new A(); // This calls new B, which calls new A, repeat ad infinitum
您可以通过在构造函数之外实例化另一个对象的实例来打破这样的循环。例如,在首次访问时:
class A
{
public A()
{
}
public B B
{
get
{
if(b == null)
b = new B();
return b;
}
}
private B b;
}
class B
{
public B()
{
}
public A A
{
get
{
if(a == null)
a = new A();
return a;
}
}
private A a;
}
// ...
A obj = new A(); // new B doesn't get called yet
obj.B.Something(); // ... Now it does...
您仍然必须小心class A
不要在其构造函数中访问它自己的this.B
属性,反之亦然。但是,只要不在构造函数中调用这些方法,您就可以在方法中访问这些属性。
另一种选择是进行依赖注入。这是您将依赖项传递给对象的地方,而不是让它实例化对象本身:
class A
{
public A(B b)
{
this.B = b;
}
public B B;
}
class B
{
public B(A a)
{
this.A = a;
}
public A A;
}
// ...
A someA = new A(
new B(
null)); // You have to break the cycle somewhere...
someA.B.A = someA;
// or ...
class ABFactory
{
public static A CreateA(/* options for a */, /* options for b */)
{
A result = new A(
new B(
null));
result.B.A = result;
return result;
}
}
请注意,依赖注入并不是为了解决这个问题而发明的,但它可以在这种情况下工作。有了它,你就可以高枕无忧了,因为你知道你再也不会遇到这个问题了。