What does exclamation mark mean before invoking a method in C# 8.0?

28,777

Solution 1

This would be the null forgiving operator.
It tells the compiler "this isn't null, trust me", so it does not issue a warning for a possible null reference.

In this particular case it tells the compiler that Entity isn't null.

Solution 2

! is the Null-Forgiving Operator. To be specific it has two main effects:

  • it changes the type of the expression (in this case it modifies Entity) from a nullable type into a non-nullable type; (for example, object? becomes object)

  • it suppresses nullability related warnings, which can hide other conversions

This seems to come up particularly with type parameters:

IEnumerable<object?>? maybeListOfMaybeItems = new object[] { 1, 2, 3 };

// inferred as IEnumerable<object?>
var listOfMaybeItems = maybeListOfMaybeItems!;

// no warning given, because ! supresses nullability warnings
IEnumerable<object> listOfItems = maybeListOfMaybeItems!;

// warning about the generic type change, since this line does not have !
IEnumerable<object> listOfItems2 = listOfMaybeItems;

Solution 3

This is called the null-forgiving operator and is available in C# 8.0 and later. It has no effect at run time, only at compile time. It's purpose is to inform the compiler that some expression of a nullable type isn't null to avoid possible warnings about null references.

In this case it tells the compiler that Entity isn't null.

Share:
28,777
icn
Author by

icn

Updated on May 28, 2021

Comments

  • icn
    icn about 3 years

    I have found a code written in C# seemingly version 8.0. In the code, there is an exclamation mark before invoking a method. What does this part of the code mean, and above all, what are its uses?

    var foo = Entity!.DoSomething();
    
  • Peter Cordes
    Peter Cordes over 4 years
    So this is just to silence warnings? It can't affect performance, can it, because it's a managed language so the compiler can't accept source-code promises unless it can prove they're always true, as far as code-gen that would break in exciting ways if the condition was false. (I assume null-deref usually just catches the hardware -> OS exception so it doesn't actually conditional branch every time anyway, and there wouldn't be any saving in this case.)
  • Ross Presser
    Ross Presser over 4 years
    @Peter-cordes: Looks like you're right. From the link: The null-forgiving operator has no effect at run time. It only affects the compiler's static flow analysis by changing the null state of the expression. At run time, expression x! evaluates to the result of the underlying expression x.
  • EriF89
    EriF89 almost 4 years
    You may even find it useful to write null!, for instance when deserializing with complete confidence that the property will be in the serialized data. Very ironic use case if you ask me and in general it's probably better to use the [JsonConstructor] attribute, but I think it illustrates the nature of this operator and when you might want to use it.