使用继承来创建自定义,类型安全,null安全的集合?

时间:2010-04-04 18:23:50

标签: c# oop inheritance programming-languages

我不清楚以上陈述。如果有人可以解释我们如何使用继承来创建自定义,类型安全和空安全集合,那会很棒吗?

由于

2 个答案:

答案 0 :(得分:3)

好吧,您可以从Collection<T>派生一个新类型并覆盖SetItemInsertItem:如果新值为null,则抛出异常。那是你想到的那种吗?

那将是:

  • 自定义:嗯,您正在覆盖自定义正常行为的方法
  • 类型安全:源自Collection<T>;基类可以防止添加不适当类型的值
  • Null-safe:您的覆盖将阻止空值出现在集合

你甚至可以保持通用:

// Note: you could include "where T : class"; on the other hand
// you might have some reason to want a NullSafeCollection<int?>
// which you knew had no null values in.
public class NullSafeCollection<T> : Collection<T>
{
    protected override InsertItem(int index, T item)
    {
        if (item == null)
        {
            throw new ArgumentNullException("item");
        }
        base.InsertItem(index, item);
    }

    // Likewise for SetItem
}

答案 1 :(得分:2)

我认为问题在于模糊的术语“无效安全”。

通常,对于类型安全集合,您使用泛型而不是继承。

所以我想我们想要的是一个派生集合,它在一些标准泛型集合之上添加了“null安全检查”(在你的情况下意味着什么)。除了在C#中,泛型集合不使用虚函数,因此它们不能被扩展(无论是谁而选择在没有密封类的情况下这样做也应该永远禁止编程)。

因此,您必须使用旧的.NET 1.x非泛型集合(如Collection),并使用“类型安全检查”和“空安全检查”覆盖它们。

另一方面,如果您使用的是“null safe”,那么更常见的集合,例如List<T>LinkedList<T>Stack<T>,{{1已经“空安全”,因为如果你传递Queue<T>它们不会崩溃或产生异常。另一方面,null不是空安全的,因为它在参数上调用GetHashCode。您必须重新编写它们以定义Dictionary<TKey,TValue>的哈希码。 null实际上是这样做的,将HashSet<T>定义为0的哈希值。同样,对于nullSortedList<TKey,TValue>,您必须定义排序顺序中SortedDictionary<TKey,TValue>的位置。

据我所知,没有办法让这些集合表现正常。这些类中缺少null支持不是由传入null时散列函数或比较器失败引起的,而是由所有面向公众的API中的先发制人检查引起的。这些不能通过公共继承来修复,而C#(通常是.NET)不允许私有继承。从好的方面来说,null不会让底层词典看不到空键。但是它扩展System.Collections.ObjectModel.KeyedCollection<TKey,TItem>以通过包含而不是继承来增加空安全性。