views:

80

answers:

2

I am not clear with above statement. It would be great if anybody can explain how we can use inheritance to create a custom, type safe and null safe collection ?

Thanks

+3  A: 

Well, you could derive a new type from Collection<T> and override SetItem and InsertItem: throw an exception if the new value is null. Is that the kind of thing you were thinking of?

That would be:

  • Custom: well, you're overriding methods to customise the normal behaviour
  • Type-safe: by virtue of deriving from Collection<T>; the base class prevents values of an inappropriate type being added
  • Null-safe: your overrides would prevent null values from ever being present in the collection

You could even keep it generic:

// 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
}
Jon Skeet
oh no, Skeet is in the house, there goes any chance of an upvote let alone accepted answer
Ben Voigt
@Ben: Well currently you have an upvote and I don't, so... :)
Jon Skeet
+2  A: 

I think the problem lies in the ambiguous term "null safe".

In general, for a typesafe collection you'd use generics, not inheritance.

So I suppose what's desired is a derivative collection that adds "null safety checks" (whatever that means in your case) on top of some standard generic collection. Except in C# the generic collections don't use virtual functions, so they can't be extended (whoever chose to do that without also making the classes sealed should be forever barred from programming).

So you'd have to use the old .NET 1.x non-generic collections like Collection, and override them with "type safety checks" and "null safety checks".

On the other hand, if you are using "null safe" in the sense I would, then the more common collections such as List<T>, LinkedList<T>, Stack<T>, Queue<T> are already "null safe" in that they don't crash or generate an exception if you pass null. On the other hand, Dictionary<TKey,TValue> is not null-safe since it calls GetHashCode on the argument. You'd have to rework them to define what the hash code of null is. HashSet<T> actually does this, defining 0 as the hash of null. Similarly for SortedList<TKey,TValue> and SortedDictionary<TKey,TValue>, you'd have to define where null lies in the sort order.

As far as I can tell, there's no way to make these collections behave correctly. The lack of null support in these classes isn't caused by the failure of the hashing function or the comparer when null is passed in, it's caused by pre-emptive checks in all the public-facing APIs. These can't be fixed by public inheritance, and C# (.NET in general) doesn't allow private inheritance. On the bright side, System.Collections.ObjectModel.KeyedCollection<TKey,TItem> goes out of its way to not let null keys be seen by the underlying dictionary. However it extends Dictionary<TKey,TValue> to add null safety through containment, not inheritance.

Ben Voigt
I think it's reasonable to infer that a "null-safe collection" is one which prevents null values from being added. I'd say that using generics and using inheritance are orthogonal choices.
Jon Skeet
Not for `List<T>`, `LinkedList<T>`, `Dictionary<T1,T2>`, and any number of other generic collections which don't provide virtual functions to override behavior. When you combine that with .NET "all inheritance is public" rule, you can't enforce additional invariants. Of course the exception is the System.Collections.ObjectModel generic classes as you pointed out.
Ben Voigt