2
votes

I am trying to learn the null conditional operator. From book I learnt, that for example if I pass string[] array to method, I can instead of using conditional scope, use null conditional operator to check if passed string[] array is not null, because for example in method I will want to use .Length property which if I passed null to it, it will cause runtime error.

All of that I understand, but when I want to use it with nullable int and .Value property from generic Nullable structure, it already throwing compiler error on me.

I think problem will be, that I don't understand what really this '?' doing after suffixed variable is null. I thought that it just skips that property or method that is after it, but maybe it pass that null and just hide exception. I really don't know, and so I want to ask what is really doing this Null Conditional Operator in more depth, and why does this nullable int example is causing error.

Code with Error:

 class Program
{
    static void Main(string[] args)
    {
        string text = null;
        Console.WriteLine("Variable contains: {0}", text?.Length); //All OK

        int? nullableInt = null;
        Console.WriteLine("Variable contains: {0}", nullableInt?.Value); //Compiler error

        Console.ReadLine();
    }
}

Edit: CompilerError message:

'int' does not contain a definition for 'Value' and no extension method 'Value' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)

Edit2: This post is duplicate of: null conditional operator not working with nullable types? However I was not able to understand problem from this post, but I managed to get it thanks to post from @adjan https://stackoverflow.com/a/44613674/7477611 where he explained it well, but in my procces of trying to learn it, I made one better explanation for someone who will read this later and maybe for someone who will be on same position as I was.

If you use ‘?’ operator on nullable type for example int?.Member (Member - some method, property...), than if variable is null, it skips member, but if it has value for example 5, then operator ‘?’ return variable.GetValueOrDefault(), which returns just int value. (return underlying type of Nullable), this is almost what @adjan said. But I will present here code that for me explained everything:

 static void Main(string[] args)
    {
        int? number = null;

        variable?.Member

        // in fact operator '?' is doing folowing:
        if (number.HasValue)
        {
            Console.WriteLine(number.GetValueOrDefault().GetType()); //System.Int32
        }
        else
        {
            Console.WriteLine(number); //null
        }
    }

As you can see number.GetValueOrDefault() returns System.Int32 data type, and if you want to use .Value property it has to be Nullable type, and System.Int32 isn't nullable type so it has not acces to .Value member. That's why it causes an error.

Hope it helps :) Thank you for your answers. :)

5
You should always include the full error message in your question - UnholySheep

5 Answers

8
votes

The variable?.Member on a nullable type of a value type T actually translates to a function roughly like

if (variable.HasValue)
    return variable.GetValueOrDefault().Member;
else
    return null;

variable.GetValueOrDefault() is of the type T, not Nullable<T>. Only Nullable<T> has a member Value (unless it is your own struct that contains a member Value, but e.g. int from your code does not).

2
votes
nullableInt?.Something

is syntactic sugar for:

nullableInt is null ? null : nullableInt.Value.Something

Thus there is no need to put the .Value there. Since if you do, you are effectively doing nullableInt.Value.Value

The equivalent code for what you want by nullableInt?.Value is nullableInt (by itself).

See also:

null conditional operator not working with nullable types?

0
votes

Nullable value types are special types. When you use nullableInt?, your result is effectively of type int, which has no Value property.

Null-conditional operator only makes sense for reference types and for string as a special case of immutable reference type.

0
votes

The following code illustrates the problem:

string[] temp = null;
int cc = -1;
if (temp == null)
{
    cc = 0;
}
else
{
    cc = temp.Count();
}

There is a difference between an empty array (count() = 0) and an array which is null.

Your code becomes:

Console.WriteLine("Variable contains: {0}", args?.Count() ?? 0); //All OK
Console.WriteLine("Variable contains: {0}", nullableInt?.ToString() ?? "woops"); //now ok
0
votes

In your code you are trying to access the member Value of nullableInt, but since this member doesn't exist so this code can't be compiled.

The ?. Operator is an accessor. It return null at runtime if the accessed member exist and is not set or set to null. By contrast the standard accessor (.) will raise a Null reference exception in this scenario.

Try replace your code by something like nullableInt ?? 0. ?? Is the null-coalescing operator and will replace null by the empty string.