0
int? number1;//Nullable variable
int number2;//Not nullable variable

//After a while
number1 = 100;

number2 = number1! + 1;
//Compile error: Cannot convert source type 'System.Nullable<int>' to target type 'int'

I don't want to use number1 ?? 0 etc. for not change my logic(consistency). (it can throw exceptions if number1 is null, no problem)

Doesn't ! means 'Trust me it is not null!' ?

Why does C# not trust me in this case?

I know null-forgiving basics but why does the ! operator not work here?

Why doesn't number1! act like NotNull in this case?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
MarsPeople
  • 1,772
  • 18
  • 30
  • 5
    `int?` is fundamentally different from, say, `string?` because `int?` is really of type `Nullable` while `string?` is still a `string` type, but it explicitly can be null. You have to use `number2 = number1.Value + 1` instead. – Matthew Watson Dec 14 '22 at 15:32
  • Try `!!` : https://stackoverflow.com/questions/71063730/what-is-double-exclamation-mark-in-c#:~:text=The%20double%20exclamation%20mark%20!!,nameof(arg))%3B%20%7D%20Console. – KYL3R Dec 14 '22 at 15:34
  • 2
    @KYL3R `!!` was a beta language feature to throw if a parameter is null, but it's since been removed from the language. – Matthew Watson Dec 14 '22 at 15:35

2 Answers2

4

You must get the int value out of the int? through the Value property because you need a int result here. You can still use the null-forgiving operator to access this property.

number2 = number1!.Value + 1;

Note that the null-forgiving operator is not doing a cast or conversion. It only tells the compiler: "I know what I am doing, this value is not null". This suppresses the compiler warning "Nullable value type may be null."

If you must test if the nullable int is not null, you can use pattern matching

if (number1 is int n) {
    number2 = n + 1;
}

or you can use the null-coalescing operator if using 0 instead of null is acceptable.

number2 = number1 ?? 0 + 1;

Here number1 ?? 0 converts a null value into 0. (This might have been what you thought the ! did)

Additional information: If you are in a nullable context, then the compiler checks whether a value can be null. If it thinks it can, e.g., because you have not tested if(number1 is not null), then it issues the warning "Nullable value type may be null.". But you might be smarter than the compiler and know that your logic ensures the value not to be null. Then you would use the null-forgiving operator to tell the compiler that everything is okay. ! only suppresses this warning. It does not influence what the code does. If you do not get the warning, then do not use the !. If you get the warning, either use the ! or use my 2nd or 3rd solution or ensure that the number is not null with the null-coalescing assignment operator number1 ??= 0;


I would like to add that a nullable value type is very different from a nullable reference type.

  • Value type: E.g. int? is a synonym for the struct Nullable<int>.
  • Reference type: E.g. string? is the same type as string with a hint telling the compiler that we consider null to be a legal value.
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
0

The point is that the result of number1! + 1; is int? that cannot be assigned to number2 declared as int. As said here, "The null-forgiving operator has no effect at run time. It only affects the compiler's static flow analysis", which means it does not know that your number1 is not null.

Roman Ryzhiy
  • 1,540
  • 8
  • 5