2017-05-04 94 views
5

真實世界的例子很簡單。有一所房子,房子有牆壁等。現在子類中的父元素

class Room { 
    public List<Wall> Walls{get; set;} 
} 

class Wall { 
    public List<WallObject> WallObjects{get; set;} 
} 

開發者已經在幾年前增加了小產權房的牆壁類:

class Wall { 
public List<WallObject> WallObjects{get; set;} 
public Room Room{ get; set; } 
} 

這是非常愉快的在此對象的類。人們可以在許多地方訪問父元素(430)。但我認爲它不屬於那裏,有時會導致錯誤,因爲您不設置或更改它。

除了在許多情況下的方法切換,還有其他方法嗎?

回答

1

有很多方法可以很容易地解決這個問題,但通常我會選擇更改所用列表的類型,並使用適當的事件來註冊和取消註冊父項。

public class Room 
{ 
    public ObservableCollection<Wall> Walls { get; } = new ObservableCollection<Wall>(); 

    public Room() 
    { 
     Walls.CollectionChanged += Walls_CollectionChanged; 
    } 

    private void Walls_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     switch (e.Action) 
     { 
      case NotifyCollectionChangedAction.Add: 
       { 
        foreach (Wall w in e.NewItems) 
        { 
         w.Room = this; 
        } 

        break; 
       } 
      case NotifyCollectionChangedAction.Remove: 
       { 
        foreach (Wall w in e.OldItems) 
        { 
         w.Room = null; 
        } 

        break; 
       } 
     } 
    } 
} 
1

你說得對,信息是多餘的。總是有可能中的List<Wall>可能包含牆,其中Room屬性指的是不同的房間,這將是一個錯誤。因此,要麼將其從Wall中刪除,要麼確保每個Wall都將在設置者Walls中進行檢查。如果牆壁的Room!= this,您可以拋出異常或更改它。

所以我修改Room類一點點:

public class Room 
{ 
    private List<Wall> walls; 

    public Room(): this(new List<Wall>()) 
    { 
    } 

    public Room(List<Wall> walls) 
    { 
     this.Walls = walls; 
    } 

    public List<Wall> Walls 
    { 
     get 
     { 
      return this.walls; 
     } 

     set 
     { 
      foreach (Wall wall in value) 
      { 
       if (wall?.Room != this) 
       { 
        throw new ArgumentException("Every wall's room must be this Room instance", nameof(Walls)); 
       } 
      } 
      this.walls = value; 
     } 
    } 
} 

由於房間通常有4個牆壁它不應該是一個大問題。