After writing this question I found out that
Nullable<T>
has a type constraint ofstruct
onT
so you cannot actually use Nullable for
reference types. However, some good answers interpreted the questions
as 'if you could' or 'if you would write your own Nullable or
NonNullable type'. This interpretation has lead to some nice answers
so I've decided to not close or delete the question.
I know the nullable construct in C# was introduced to support null for value types. However, the language does not seem to have a problem with using nullable on other types. I wonder if this is a bad practice. I've come up with some arguments for both sides, but I can't decide.
Pros
- Foo? x makes it exceptionally clear that a variable can be null.
Cons
- If Foo is not a value type we create a struct with a reference type which is a bad practice.
- Why wrap a variable that can already be null with more boilerplate code. Comments or naming can already indicate that the value can be null.
- Not marking the object as nullable does not guarantee that it will not be null. So inconsistent use will lead to confusion.
- Performance overhead? (Extremely neligible in most cases).
- It makes the code slightly harder to read
With nullable
Foo? x;
// <snip>
x = null;
// <snip>
if(x.HasValue) { x.Value.Bar(); }
Without
Foo x; // Might be null
// <snip>
x = null;
// snip>
if(x != null) { x.Bar(); }
Best Answer
As others have said, this isn't possible, but there are a couple of easy constructs you can create yourself that achieve similar aims.
Maybe<T>
(This could also be implemented other ways, such as an
IEnumerable<T>
with the constraint that it has exactly 0 or 1 items)NotNull<T>
Maybe<T>
essentially just reimplementsNullable<T>
for reference types. It has similar advantages and disadvantages to the ones described in your post. It's probably only valuable if you have a convention throughout your project to use it for any value wherenull
is a valid value.NotNull<T>
is likely to be more directly what you want, as MainMa stated. By passing around values wrapped in this type you can remove the need to check whether a value is null in a guard clause. However, there's no way to completely prevent aNotNull<T>
from itself being null. You can't make it a struct because of the requirement of a default constructor, which would leaveValue
null.(EDIT: As others have pointed out, in C# 6 you will be able to have a parameterless constructor for a struct, but it will not be used when initializing arrays or getting the result of
default(T)
, so you still can't really rely on the guarantee thatValue
won't be null)So while both of these potentially add some value in signalling whether
null
should be considered valid or not, they're both limited in that they require constant adherence to a convention, in addition to the boilerplate and readability issues. Whether the trade-off is worth it would be a matter of judgement, but remember that code contracts or other static analysis tools also exist as a possible alternative way of addressing this issue.