Why are you getting the warning?
You have enabled the nullable reference types (NRT) feature of C#. This requires you to explicitly specify when a null
may be returned. So change the signature to:
public TEntity? Get(Guid id)
{
// Returns a TEntity on find, null on a miss
return _entities.Find(id);
}
And the warning will go away.
What is the use of NRTs?
Other recent changes - specifically around pattern matching - then tie in really nicely with NRT's. In the past, the way to implement the "try get pattern" in C# was to use:
public bool TryGet(Guid id, out TEntity entity)
Functional languages offer a better approach to this: the maybe (or option) type, which is a discriminated union (DU) of some value and none
. Whilst C# doesn't yet support DU's, NRT's effectively provide that maybe type (or a poor man's equivalent) as TEntity?
is functionally equivalent to Maybe<TEntity>
:
if (Get(someId) is TEntity entity)
{
// do something with entity as it's guaranteed not null here
}
else
{
// handle the fact that no value was returned
}
Whilst you can use this type of pattern matching without using NRTs, the latter assists other developers as it makes clear that the method will return null
to indicate no value. Change the name to TryGet
and C# now provides that functional style try get pattern:
public TEntity? TryGet(Guid id) => _entities.Find(id);
And with the new match expression, we can avoid out parameters, mutating values etc and have a truly functional way of trying to get an entity and creating one if it doesn't exist:
var entity = TryGet(someId) switch {
TEntity e => e,
_ => Create(someId)
};
But is it wrong to return null?
There has been vast amounts written on why null was the billion dollar mistake. As a very crude rule of thumb, the existence of null
likely indicates a bug. But it's only a crude rule of thumb as there are legitimate use-cases for null in the absence of Maybe<T>
. NRT's bridge that gap: they provide a relatively safe way of using null
to indicate no value. So I'd suggest - for those using newer versions of C# - there is nothing wrong with returning null
as long as you enable the NRT feature and you stay on top of those CS8603
warnings. Enable "treat warnings as errors" and you definitely will stay on top of them.
TEntity?
and compiler simply warns them that there is some obvious mismatch between what they promised to return and what code actually does.TEntity?
syntax didn't exit. It was implied that any object could benull
.