7

Consider the following code, written in a nullable-references-enabled context:

static string GetStr() => "test";

public static void Main() {
    var s = GetStr();
}

s is implicitly typed as a string? rather than a string.

This is by design, as it's mentioned on MSDN's official documentation for var:

When var is used with nullable reference types enabled, it always implies a nullable reference type even if the expression type isn't nullable.

But why is this? Is it because the variable may be re-assigned later?

Furthermore, even though it's typed as string? I can dereference it without a warning:

if (s.Length > 10) return; // Emits no compiler warning

However, if I create another method that does return a string? the compiler now emits a warning if I attempt a dereference, even though both variables are typed as string?:

static string? GetStrMaybe() => "test";

public static void Main() {
    var s = GetStrMaybe();
    if (s.Length > 10) return; // Compiler emits a warning because I'm dereferencing 's' without checking for null
}

Is the answer basically "the compiler is tracking null state in the background", and that the implicitly-typed variable types are kind of to-be-ignored?

I find this weird because in both cases, s is typed as string?, but only in the latter example does the compiler emit a warning if I dereference without a check. Which, to be clear, is what I'd expect in the end, but it's just the way we get there that's confusing me.

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
Xenoprimate
  • 7,691
  • 15
  • 58
  • 95
  • 3
    "*Is it because the variable may be re-assigned later?*" -- yes, in a nutshell. Note that the *flow state* of the variable is "not null", so the compiler won't complain if you dereference it. – canton7 Jan 08 '21 at 13:27
  • 2
    "*Is the answer basically "the compiler is tracking null state in the background", and that the implicitly-typed variable types are kind of to-be-ignored?*" -- there was some discussion on whether to not have nullability annotations at all for locals IIRC, and just rely on the flow state, but that didn't end up being the path chosen – canton7 Jan 08 '21 at 13:28
  • I'm not quite following. `string` is a reference type, so it's nullable anyway. – Nyerguds Jan 08 '21 at 14:32
  • 3
    @Nyerguds This question is about [Nullable Reference Types](https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references), introduced in C# 9 – canton7 Jan 08 '21 at 14:40
  • @canton7 Oh. I see. Interesting. Did not know that was a thing. I generally avoid `var` on principle, because, while it avoids verbosity, it also removes clarity. This question only highlights that. – Nyerguds Jan 08 '21 at 14:42
  • @Nyerguds: _"while it avoids verbosity, it also removes clarity"_ That's not an argument against using `var`, that's an argument against _constantly_ using `var`. It makes sense to explicitly define the type in OP's example (assuming the real life method didn't state the return type in its name), but explicitly mentioning the type in `var person = new Person();` seems irrelevant, no? It's mostly for those latter cases that `var` was introduced. Not to be used willy nilly. – Flater Jan 08 '21 at 15:07
  • 2
    This is not a question on whether or not to use `var`: please keep religious wars out of places they don't belong :) – canton7 Jan 08 '21 at 15:14
  • @Flater `var` was introduced to handle anonymous types used in Linq queries. – juharr Jan 08 '21 at 16:56
  • @Flater Actually, as I said, this question specifically highlights the fact that, depending on project settings, that specific example could end up with either `Person` or `Person?` as the variable type. So, yes, it _still_ reduces clarity. – Nyerguds Jan 09 '21 at 01:52
  • Because adoption would be painful otherwise. You’d have to change existing code to use explicit types in many instances. – Julien Couvreur Jan 09 '21 at 22:07

0 Answers0