Ala*_*ain 3 c# oop inheritance .net-3.5
我想创建一个自定义 observable 集合(可以在 XAML 中绑定),但我想跟踪需要覆盖 observable 集合方法的其他信息。ObservableCollection 方法不是虚拟的,这意味着“覆盖”它们的唯一方法实际上只是使用“new”关键字隐藏它们。这是我的意思的一个简单示例:
//Tracks how many objects of each type are in this collection
class CustomCollectionInherited:ObservableCollection<Object>
{
private Dictionary<Type, UInt32> _count = new Dictionary<Type,uint>();
public UInt32 getTypeCount(Type T)
{
return _count[T];
}
#region Base Method 'Overrides'
new public void Add(Object item)
{
base.Add(item);
if (!_count.ContainsKey(item.GetType())) {
_count[item.GetType()] = 1;
} else {
_count[item.GetType()] += 1;
}
}
new public bool Remove(Object item)
{
if (base.Remove(item))
{
_count[item.GetType()] -= 1;
return true;
}
return false;
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
我有两个问题。首先,虽然我想从 ObservableCollection 继承很多方法,例如枚举器、INotifyCollectionChanged 接口等,但有很多方法我不想继承。即,修改集合的方法,例如 Clear()、ClearItems()、Insert()、InsertItem() 和其他 13 个会导致我的集合的类型计数不同步的方法。这似乎是组成的论据。
第二个问题是向上转换- 程序员可能会意外绕过我的自定义实现,通过使用我的集合的方式将其向上转换为继承的类型。例如:
myCustomObj.AddToCollection( myCustomCollectionInherited );
...
void CustomObj.AddToCollection( Collection c )
{
c.Add(this);
}
Run Code Online (Sandbox Code Playgroud)
这是一个非常人为的示例,但在这种情况下,将使用继承的“Add”方法,并且我的集合的类型计数将再次不同步。除非我的集合监视 base.CollectionChanged 事件并每次从头开始重建计数,否则似乎没有任何解决方法,这完全违背了在 O(1) 时间内维护计数的目的。
基于这些问题,我开始认为适当的解决方案是创建一个包含ObservableCollection的类。但请记住,我需要它像可观察集合一样绑定到 XAML,因此我必须实现 ObservableCollection 实现的所有相关接口,以便它可以以相同的方式绑定到 UI。一个例子如下:
//Tracks how many objects of each type are in this collection
class CustomCollectionEncapsulated : IList<object>, INotifyCollectionChanged
{
private ObservableCollection<Object> _base = new ObservableCollection<object>();
private Dictionary<Type, UInt32> _count = new Dictionary<Type, uint>();
public UInt32 getTypeCount(Type T)
{
return _count[T];
}
public void Add(object item)
{
_base.Add(item);
if (!_count.ContainsKey(item.GetType())) {
_count[item.GetType()] = 1;
} else {
_count[item.GetType()] += 1;
}
}
public bool Remove(object item)
{
if (_base.Remove(item))
{
_count[item.GetType()] -= 1;
return true;
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
当然,上面的内容本身并不能编译,因为 IList 实现了 ICollection、IEnumerable、IEnumerable,所有这些都有我需要实现的方法,依此类推,直到我最终拥有 20 个左右的额外方法和数百行代码所有这些都说
Type methodINeedToImplement(Params)
{
return _base.methodINeedToImplement(Params);
}
Run Code Online (Sandbox Code Playgroud)
或者
Type methodINeedToImplement(Params)
{
throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)
继承的主要原因是程序员不需要为 95% 没有改变的方法和事件做所有这些工作。
那我该怎么办?我绝对无法说服我的老板,保护这个自定义集合的最佳方法是使用封装并明确实现 20 种新方法。与此同时,我们已经遇到了其他人使用这个自定义集合的错误,他们通过使用我们不支持但无法通过继承隐藏的基本 ObservableCollection 方法来搞砸它。
ObservableCollection 被设计成一个基类,你只是在看错误的方法,而不是像 Add、Remove、Clear 等公共方法。你应该覆盖像 InsertItem、MoveItem 等受保护的虚拟方法。检查文档以获取完整的列表可覆盖的东西。