Reputation: 2808
I am trying to convert an existing project to using nullable reference types properties using non-nullable properties during initialization.
I am using this approach for getting properties which should exist:
public class Dog
{
private Person? _person;
public int Id { get; set; }
public string Name { get; set; }
public Person Person
{
get => _person ?? throw new InvalidOperationException(
$"Unset property {nameof(_person)}. You probably forgot to Include it");
set => _person = value;
}
}
But it's tedious to write this for almost every property, so I've tried to make a generic ThrowOrGet()
function:
public static class Util
{
public static T ThrowOrGet<T>([AllowNull] T obj)
{
if (obj == null)
{
throw new InvalidOperationException(
$"Unset property {nameof(obj)}. You probably forgot to Include it");
}
return obj;
}
}
Which is used like this:
public class Dog
{
private Person? _person;
public int Id { get; set; }
public string Name { get; set; }
public Person Person
{
get => Util.ThrowOrGet(_person); ---> "Possible null reference return"
set => _person = value;
}
}
But the the function Util.ThrowOrGet(_person);
now says that it's a possible null
reference return. If I inline the function, it works as intended.
Is there a way to make a generic function that does this?
Upvotes: 0
Views: 131
Reputation: 5850
If you're only going to use ThrowOrGet
on reference types (which you should, as it doesn't make sense for value types), then you should declare it like this:
public static T ThrowOrGet<T>(T? obj) where T : class
{
if (obj == null)
{
throw new InvalidOperationException(
$"Unset property {nameof(obj)}. You probably forgot to Include it");
}
return obj;
}
This says that the function accepts a nullable argument, and always returns a non-nullable reference. It's better to follow this pattern than rely on the attributes, as they're really just there for complex cases, which this is not.
Upvotes: 4