I have the following method which takes a Type as a parameter and checks if it is IEnumerable<T>. If it is, it returns true and sets the type of T in an out variable, otherwise it returns false.
private static bool TryGetEnumeratedType(Type type, [NotNullWhen(true)] out Type? enumeratedType)
{
enumeratedType = null;
bool isEnumerable = type.GetInterfaces().Any(i => i.GetTypeInfo() == typeof(IEnumerable));
if (!isEnumerable)
{
return false;
}
Type? genericType = type.GetGenericArguments().FirstOrDefault();
if (genericType is null)
{
return false;
}
enumeratedType = genericType;
return true;
}
If I call the method this way, there is no issue:
Type fieldType;
if (TryGetEnumeratedType(inType, out Type? type))
{
fieldType = type;
}
else
{
fieldType = inType;
}
But if I assign the result to a variable and check against the variable, I get a compiler warning when assigning fieldType = type saying that type may be null.
Type fieldType;
bool isEnumerable = TryGetEnumeratedType(inType, out Type? type);
if (isEnumerable)
{
fieldType = type;
}
else
{
fieldType = inType;
}
Is this a bug, or am I missing something?
I believe that has nothing to do with NotNullWhen. The compiler just doesn't do that kind of work - it doesn't go into deep checks of "where did that variable come from". Doing that would probably be 1) hard to implement and 2) you wouldn't know where to stop: how high up the call stack should compiler go to ensure there is no null assigned to your value? That would probably be very resource-intensive. This answer discusses it a bit.
Consider these two methods, for example:
public int GetInt() //no warning
{
if (true)
return 1;
}
public int GetAnotherInt() //CS0161: not all code paths return a value
{
var @true = true;
if (@true)
return 1;
}
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