141

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();
Ashkan Mobayen Khiabani
  • 33,575
  • 33
  • 102
  • 171
icn
  • 1,783
  • 2
  • 7
  • 13

3 Answers3

167

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.

Mor A.
  • 3,805
  • 2
  • 16
  • 19
  • 5
    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.) – Peter Cordes Dec 08 '19 at 12:27
  • 2
    @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.` – Ross Presser Dec 08 '19 at 13:21
  • 3
    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. – EriF89 Sep 04 '20 at 14:30
40

! 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;
Dave Cousineau
  • 12,154
  • 8
  • 64
  • 80
37

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. Its 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.

Javier Silva Ortíz
  • 2,864
  • 1
  • 12
  • 21