【发布时间】:2017-03-02 20:45:09
【问题描述】:
假设您有一个由“父母”和“孩子”组成的数据结构,其中父母和孩子之间的引用是相互的:
借用a previous post,编写如下代码保证父母和孩子之间的相互引用(少用Reflection):
public static class Base
{
private interface IParent
{
List<Child> Children { get; }
}
public class Parent : IParent
{
private readonly List<Child> _children = new List<Child>();
public readonly ReadOnlyCollection<Child> Children = _children.AsReadOnly();
List<Child> IParent.Children { get { return _children; } }
}
public class Child
{
private Parent _parent;
public Parent Parent
{
get
{
return _parent;
}
set
{
if(value == _parent)
return;
if(_parent != null)
{
((IParent)_parent).Children.Remove(this);
_parent = null;
}
if(value != null)
{
((IParent)value).Children.Add(this);
_parent = value;
}
}
}
}
}
现在假设您想要一个类似的结构,但您还想要类型安全。也就是说,TParent 的实例只能引用 TChild 的实例,而 TChild 的实例只能引用 TParent 的实例。
我想出了这个解决方案:
public static class Base<TParent, TChild>
where TParent : Base<TParent, TChild>.Parent
where TChild : Base<TParent, TChild>.Child
{
private interface IParent
{
List<TChild> Children { get; }
}
public class Parent : IParent
{
private readonly List<TChild> _children = new List<Child>();
public readonly ReadOnlyCollection<TChild> Children = _children.AsReadOnly();
List<TChild> IParent.Children { get { return _children; } }
}
public class Child
{
private TParent _parent;
public TParent Parent
{
get
{
return _parent;
}
set
{
if(value == _parent)
return;
if(_parent != null)
{
// Oh no, casting!
((IParent)_parent).Children.Remove((TChild)this);
_parent = null;
}
if(value != null)
{
// Oh no, casting!
((IParent)value).Children.Add((TChild)this);
_parent = value;
}
}
}
}
}
虽然这有效,但 Child 在 Child.Parent.set 内被转换为 TChild 的点让我有点担心。虽然我不确定有没有办法使用这个抛出 InvalidCastException 的类,但它可能仍然无法破解。
有没有更简洁的方法来实现这个效果?
【问题讨论】:
-
天哪,请不要这样做。请参阅 blogs.msdn.microsoft.com/ericlippert/2011/02/03/… 了解为什么这是 C# 中的错误模式。
-
@EricLippert - 你确实说过,“在实践中,有时使用这种模式确实可以以其他方式在 C# 中难以建模的方式切实解决问题”。当我指定对象模型而其他人只是使用它时,我发现这种方法很有用。这是否减轻了您看到的问题?
标签: c# generics type-safety