I have a special generic class which contains a complicated collection of objects . I am creating an extension method to search the class to see if a specific item exists by name. It's worth noting that type T
doesn't have any particular constraints. It could be a class/reference type or a numeric type or a string.
My extension method looks like this:
public static bool TryGetItem<T>(this MySpecialClass<T> msc, string name, out T item)
{
T? i = msc.FindItemByName(name);
if (i != null)
{
item = i;
return true;
}
else
{
item = default(T); //warning on this line.
return false;
}
In case it is not obvious, the use case for the extension method would be like:
//Example if the class is holding integers.
if (msc1.TryGetItem("somename1", out int item)
{
//do something with 'item'
}
//Example if the class is holding MyClass1 objects
if (msc2.TryGetItem("somename2", out MyClass1 item)
{
//do something with 'item'
}
I'm in Visual Studio 2022, using Core 6, and I have the "nullable" option enabled. As a result I get an green squiggly underline on the item = detault(T);
line saying
Possible null reference assignment.
I understand why I'm getting the warning: I'm assigning default(T)
to item
which is not marked as nullable. But the nature of the method is that the out
value will never be used if the method returns false
. Obviously, VS doesn't realize this, and omitting the line causes an error, because out
parameters have to be assigned to.
This is in an extension method, and I could ignore the squiggly line, but I have the null option turned on for a reason, as I believe it forces me to create more robust code. So, I wonder if I missing a better way to handle this.
Right now I am forcing VS2022 to skip the warning by wrapping the line like so to remove it from the warning list:
#pragma warning disable CS8601
item = default(K);
#pragma warning restore CS8601
But I can't shake the feeling that I'm doing something "hacky". Is there a standard way that I should be handling this? Or is this scenario a good use of the "#pragma warning disable/restore"?
You should use the attribute MaybeNullWhenAttribute
.
Mark the out
parameter with [MaybeNullWhen(false)]
:
public static bool TryGetItem<T>(
this MySpecialClass<T> msc,
string name,
[MaybeNullWhen(false)] out T item
) {
...
}
While item
is declared with a non-nullable type, the attributes tells the compiler that it may be null when TryGetItem
returns false.
See also this section in the docs about nullable analysis attributes.