【发布时间】:2017-07-20 01:32:38
【问题描述】:
有时我发现自己经常写一个“父母”和“孩子”的数据结构,其中:
- 父级引用了 0 到 N 个不同的子级。
- 子项引用了 0 个父项或 1 个父项。
- 引用必须是相互的。对于任何给定的父母,它引用的任何孩子也必须引用给定的父母。对于任何给定的孩子,它引用的父级必须引用给定的孩子。
- 除了使用反射之外,通过使用可从两个类声明(非
private)外部访问的成员来违反上述规则是不可能的。
在实施这样的事情之前可能会采取的心理步骤可能会从这样的事情开始:
public class Parent
{
private readonly List<Child> _children = new List<Child>();
public readonly ReadOnlyCollection<Child> Children = _children.AsReadOnly();
}
public class Child
{
private Parent _parent;
public Parent Parent
{
get
{
return _parent;
}
set
{
if(value == _parent)
return;
if(_parent != null)
{
_parent._children.Remove(this);
_parent = null;
}
if(value != null)
{
value._children.Add(this);
_parent = value;
}
}
}
}
当然,这不会编译,因为Parent._children 是private。但是,您不会想将其设为私有,因为允许在 Child 或 Parent 之外进行访问可能会违反实现或其他地方的规则。
所以,我想出的一个解决方案是将Child 嵌套在Parent 中。嵌套类可以访问其嵌套类的私有成员:
public class Parent
{
private readonly List<Child> _children = new List<Child>();
public readonly ReadOnlyCollection<Child> Children = _children.AsReadOnly();
public class Child
{
private Parent _parent;
public Parent Parent
{
get
{
return _parent;
}
set
{
if(value == _parent)
return;
if(_parent != null)
{
_parent._children.Remove(this);
_parent = null;
}
if(value != null)
{
value._children.Add(this);
_parent = value;
}
}
}
}
}
我要问的问题是,是否有任何替代方法可以实现相同的目标,与这种方法相比,这些方法的缺点更少或更少?我发现这种方法的主要缺点是:
- 虽然使用
partial会有所帮助,但这可能会导致脚本变大。 - 这可能会导致比预期更深的嵌套。
- 这可能导致冗长的类名。要在
Parent之外访问Child,您必须使用Parent.Child。在类名很长的情况下,尤其是在使用泛型时,这可能会导致代码非常难看。 - 使用泛型(例如,实现编译时类型安全)可能会变得混乱。这似乎至少部分源于
Child是嵌套的,而Parent<T1>.Child是与Parent<T2>.Child不同的类型,当您希望类型安全是相互的时,这可能会导致非常难看的泛型使用,或者需要回退到使用运行时强制类型安全(尽管它可以被封装掉,通常,例如,使用非泛型抽象基,其中public访问器改为protected)。
附带说明,这可能是一个很好的例子,说明使用friend 扩展访问权限可以简化这些问题!
【问题讨论】:
-
如何在父级 Remove(Child) 中添加一个公共方法,该方法将从列表中删除子级,但在父级内部
标签: c# hierarchy encapsulation friend member-access