Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any collections in .NET that prevent null entries?

I'm specifically thinking about a collection that fulfills the contract of a set, but I think the question can apply to any kind. Are there collections in the .NET framework that prevent null entries? The specific behavior I want is this:

var set = new HashSet<object>();
bool added = set.Add(null);
Console.WriteLine(added); // prints "False"

This isn't the behavior of the built-in HashSet<T>. Are there any collections that do have this (or similar) behavior, or am I better off rolling my own? If the latter, what's the best way to go about it? Should I inherit directly from HashSet<T> or just wrap it?

EDIT: To be clear, this is just idle wondering. Mostly because I can't think of any reason I'd ever want to allow null into a set of objects. I don't have any particular need for this.

like image 851
Sean Devlin Avatar asked Feb 02 '10 18:02

Sean Devlin


People also ask

Which collection accepts null values?

HashSet - accepts one null element.

Can collection have null values?

A Set is a collection that cannot contain duplicate elements. It models the mathematical set abstraction. It does not allow duplicate elements and allow one null value at most.

Does any handle null C#?

If you have ever considered a value type variable, then it can never be assigned a NULL value, but the developers of C# can assign a NULL value to any Reference type variables.

Is it really better to return an empty list instead of null?

It is better to return empty collections rather than null when writing methods. The reason being that any code calling your method then doesn't need to explicitly handle a special null case. Returning an empty collection makes the null check redundant and results in much cleaner method calling code.


2 Answers

There isn't a built-in class just like HashSet<T> except for this single behavior.

If you need this, I'd recommend rolling your own. I do not recommend subclassing HashSet<T>, however. None of the methods (like Add, which you explicitly want to change) are virtual, as it wasn't really designed with subclassing in mind. This will cause strange usage behavior, since you'd be hiding the inherited methods.

Just encapsulate a HashSet<T>, and expose the members you need. The only real "code" you'd have to add is a single null check on the Add method - otherwise, just pass through all of the methods to the encapsulated instance.

If you want this to be a generic class, you'll need to add an extra constraint to only work with classes, since you want to have a null check:

public class ValueSet<T> : ICollection<T>, IEnumerable<T>, ICollection
    where T : class
{
     private HashSet<T> hashSet = new HashSet<T>();
     // ... Implement all members as needed...
like image 142
Reed Copsey Avatar answered Oct 03 '22 08:10

Reed Copsey


What about writing an extension method for HashSet. It may be the easiest thing to do.

public static class HashSetExtensions
{
    public static bool AddNonNull<T>(this HashSet<T> set, T item)
        where T : class
    {
        if (item == null)
            return false;

        return set.Add(item);
    }
}

You can then do this:

HashSet<object> test = new HashSet<object>();
test.AddNonNull(null); //Will return false;
like image 30
AGoodDisplayName Avatar answered Oct 03 '22 08:10

AGoodDisplayName