2010-02-09 51 views
3

我有一個包含名爲ChildrenIList<T>屬性的類。每個孩子都應該參考其父母。我的解決方案是在ParentClass.Children getter中設置ChildClass.Parent屬性。有更好的方法,還是這是最好的解決方案?在子項上自動設置父項引用

class ParentClass 
{ 
    private IList<ChildClass> _children; 

    public virtual IList<ChildClass> Children 
    { 
     get 
     { 
      // make sure each child refers to its parent (this) 
      foreach (ChildClass c in _children) 
      { 
       c.Parent = c.Parent ?? this; 
      } 
      return _children; 
     } 
     set 
     { 
      _children = value; 
     } 
    } 
} 

回答

8

它可能只是我......但這看起來像一個糟糕的設計。

如果是真正的父 - >子關係,則不應允許任何人創建孤兒子。因此,在創建時應將父母設置在孩子身上。

我可能會做這樣的事情:

class ChildClass 
{ 
    private ParentClass _parent; 

    public ChildClass(ParentClass parent) 
    { 
     _parent = parent; 
    } 
} 

然後:

class ParentClass 
{ 
    private List<ChildClass> _children; 

    public virtual ReadOnlyCollection<ChildClass> Children 
    { 
     get 
     { 
      return _children.AsReadOnly(); 
     } 
    } 

    public virtual ChildClass CreateChild() 
    { 
     // Set parent in child class constructor 
     ChildClass newChild = new ChildClass(this); 

     _children.Add(newChild); 

     return newChild; 
    } 
} 
0

與解決方案的問題是,如果所有的孩子和家長是否正確鏈接,您的代碼將重新每次檢索內部子集合時將它們鏈接起來。此外,似乎存在此問題,因爲您正在返回對私有集合的引用,之後您將失去對其包含的元素的控制權。

我建議如下:

ParentClass提供Add(ChildCLass)Remove(ChildClass)方法,以及執行親子約束存在。這可以讓孩子在任何地方創建,並且在屬於層次結構時可以正確鏈接。從層次結構中刪除時,不再鏈接。

除非集合是不可變的,否則不要返回對內部ChildClass集合的引用。返回ReadOnlyCollectionIEnumerable是優選的。

實例:

class ChildClass 
{ 
    // Prevent unauthorized clients from overriding the Parent reference. 
    public ParentClass Parent { get; internal set; } 

    // ... other methods and properties ... 
} 

class ParentClass 
{ 
    private IList<ChildClass> _children; 

    public void AddChild(ChildClass child) 
    { 
     _children.Add(child); 
     child.Parent = this; 
    } 

    public RemoveChild(ChildClass child) 
    { 
     _children.Remove(child); 
     child.Parent = null; 
    } 

    public IList<ChildClass> Children 
    { 
     get { return _children.AsReadOnly(); } 
    } 
} 
相關問題