C#'s can't make `notnull` type nullable

后端 未结 2 1983
一整个雨季
一整个雨季 2020-12-11 16:01

I\'m trying to create a type similar to Rust\'s Result or Haskell\'s Either and I\'ve got this far:

public struct Result

        
2条回答
  •  佛祖请我去吃肉
    2020-12-11 16:44

    Basically you're asking for something that can't be represented in IL. Nullable value types and nullable reference types are very different beasts, and while they look similar in source code, the IL is very different. The nullable version of a value type T is a different type (Nullable) whereas the nullable version of a reference type T is the same type, with attributes telling the compiler what to expect.

    Consider this simpler example:

    public class Foo where T : notnull
    {
        public T? GetNullValue() => 
    }
    

    That's invalid for the same reason.

    If we constraint T to be a struct, then the IL generated for the GetNullValue method would have a return type of Nullable.

    If we constraint T to be a non-nullable reference type, then the IL generated for the GetNullValue method would have a return type of T, but with an attribute for the nullability aspect.

    The compiler can't generate IL for a method which has a return type of both T and Nullable at the same time.

    This is basically all the result of nullable reference types not being a CLR concept at all - it's just compiler magic to help you express intentions in code and get the compiler to perform some checking at compile-time.

    The error message isn't as clear as it might be though. T is known to be "a value type or non-nullable reference type". A more precise (but significantly wordier) error message would be:

    A nullable type parameter must be known to be a value type, or known to be a non-nullable reference type. Consider adding a 'class', 'struct', or type constraint.

    At that point the error would reasonably apply to our code - the type parameter is not "known to be a value type" and it's not "known to be a non-nullable reference type". It's known to be one of the two, but the compiler needs to know which.

提交回复
热议问题