Наследственность - это не то же самое, что композиция.Когда вы наследуете B
от A
, вы говорите "B
- это A
".В вашем случае, когда вы наследуете Apartment
от House
, вы говорите: «Apartment
- это House
».Это, очевидно, неправда, поскольку квартира - это не дом, а часть дома.Так что Apartment
не должен наследоваться от House
.
Отношение , являющегося частью , выражается композицией.Вы сделали это, добавив список квартир в House
(и свойство House
в Apartment
).
Однако обычно вы хотите сохранить целостность между списком родителей и родительским свойством ребенка.,Например, когда вы добавляете Apartment
к House
, вы хотите, чтобы Apartment.House
был установлен соответствующим образом.
Этого нельзя добиться с помощью List<T>
.На самом деле List<T>
не предназначен для использования в качестве публичной собственности такого рода, но для внутреннего хранения данных.Для ваших целей вам понадобится System.Collections.ObjectModel.Collection<T>
, который разрешит необходимую вам настройку.
Так будет работать для отношений между House
и Apartment
.Вы должны сделать то же самое для Apartment
и Resident
:
public class House
{
public int Number { get; set; }
public string Street { get; set; }
public ApartmentCollection Apartments { get; private set; }
public House() {
Apartments = new ApartmentCollection(this);
}
}
public class Apartment
{
private House house;
public int AptNumber { get; set; }
public int AptRooms { get; set; }
public House House {
get {
return house;
}
set {
house?.Apartments.Remove(this);
house = value;
house?.Apartments.Add(this);
}
}
public List<Resident> Residents = new List<Resident>();
}
public class ApartmentCollection : Collection<Apartment> {
private readonly House parent;
public ApartmentCollection(House parent) {
this.parent = parent;
}
protected override void InsertItem(int index, Apartment item) {
if (item == null) {
throw new ArgumentNullException(nameof(item));
}
if (Contains(item)) {
return;
}
base.InsertItem(index, item);
item.House = parent;
}
protected override void SetItem(int index, Apartment item) {
if (item == null) {
throw new ArgumentNullException(nameof(item));
}
Apartment oldItem = this[index];
if (oldItem.Equals(item)) {
return;
}
int oldIndexOfItem = IndexOf(item);
base.SetItem(index, item);
oldItem.House = null;
item.House = parent;
//If the item was in the collection before, remove it from its old position
if (oldIndexOfItem >= 0) {
base.RemoveItem(oldIndexOfItem);
}
}
protected override void RemoveItem(int index) {
Apartment removedItem = this[index];
base.RemoveItem(index);
removedItem.House = null;
}
protected override void ClearItems() {
Apartment[] removedItems = new Apartment[Count];
CopyTo(removedItems, 0);
base.ClearItems();
foreach(Apartment removedItem in removedItems) {
removedItem.House = null;
}
}
}
Теперь вы можете сделать как установить Apartment.House
, так и добавлять и удалять элементы из House.Apartments
.Другая сторона всегда будет автоматически обновляться.Кроме того, ApartmentCollection
предотвратит добавление одной и той же квартиры дважды или добавление значения null
к коллекции квартир.A List<T>
не делает ни того, ни другого.