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.
HashSet - accepts one null element.
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.
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.
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.
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...
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With