Home > Software engineering >  Why isn't this property being treated as a Nullable<int>?
Why isn't this property being treated as a Nullable<int>?

Time:02-03

Given the following class

    public class Component<TValue>
    {
        public TValue? MaxValue { get; set; }
        public TValue? MinValue { get; set; }
        public TValue Value { get; set; } = default!;

        public override string ToString() =>
            $"MinValue = {MinValue}, MaxValue = {MaxValue}, Value = {Value}";
    }

Why is it that when I create an instance of Component<int> the MinValue and MaxValue properties are int instead of Nullable<int>?

        static void Main(string[] args)
        {
            var instance = new Component<int>();
            instance.Value = 42;
            Console.WriteLine(instance.ToString());
        }

I could get it to behave how I want to by adding where TValue: struct, but I am writing a Blazor component that needs to work with any numeric type (including nullables) so I can't add that constraint.

I'd like to know the logic behind why TValue? for an int should not be compiled as Nullable<Int32>.

CodePudding user response:

You did not constrain your class's type parameter neither to struct nor to class.

When you create new instance of Component with generic type parameter which is not nullable (in your case 'int') all of the properties using this generic type, will become int.

If you want your TValue to be nullable, create instance providing 'int?' as a generic type parameter.

Creating new instance with nulalble generic type

CodePudding user response:

When the type parameter T in syntax T? is not constrained to a struct it takes on the nullable reference type meaning of T?. In the cases where T is instantiated with a reference or interface type then the result will continue to be a nullable reference type. For instance if it's instantiated with string the value is treated as string?. In the case T is instantiated with a value type the ? is effectively dropped as it has no meaning.

If the desire is to have T? mean a nullable value type then T must be constrained to struct

If the desire is to have T? mean Nullable<T> when instantiated with a value type and T? when instiated with a reference type, then unfortunately there is no such syntax for that. It would require significant runtime work to provide

  • Related