I stumbled across an interesting issue where I do not have any explanation for, hoping someone could explain.
When dealing with nullable objects (pseudo) code like the following works (Note: working snipped below):
object? obj = GetNullableObject();
if(obj is null) {
return;
}
FunctionRequiringNonNullableObj(obj); // No compile error, object is known to be not null
However, doing the same, with for example long? does not:
long? literal = GetNullableLong();
if(literal is null) {
return;
}
FunctionRequiringNonNullableLong(literal); // Compiler error -> Cannot convert long? to long
Somehow the compiler seems to ignore the fact that the literal cannot be null anymore. I assume I am missing something related to performance optimization magic (or related).
Implemented both versions (object? and long?) to reproduce the issue. My expectation is that in both cases the compiler knows that the variable is not null anymore.
using System;
public class Program
{
public static void Main()
{
TestWithObject();
TestWithLiteral();
}
private static void TestWithObject() {
object? obj = ReturnOptionalObject();
if(obj is null) {
Console.WriteLine("Object is null. Returning.");
return;
}
FunctionUsingObject(obj);
}
private static void TestWithLiteral() {
long? literal = ReturnsOptionalLiteral();
if(literal is null) {
Console.WriteLine("Literal is null. Returning.");
return;
}
// Does not work, compiler error
// FunctionUsingLiteral(literal);
}
private static object? ReturnOptionalObject() {
return new object();
}
private static long? ReturnsOptionalLiteral () {
return 123L;
}
private static void FunctionUsingObject(object obj) {
Console.WriteLine("Can access object.");
}
private static void FunctionUsingLiteral(long literal) {
Console.WriteLine("Can access literal.");
}
}