Reputation: 7804
I've a project on which I enabled the new Nullable reference type feature
<Nullable>enable</Nullable>
Now let's consider this code
public class Foo { }
var foo = new Foo();
The compiler considers the foo
variable to be nullable (Foo?
).
Why is that? I don't understand.
Now with the Nullable reference type feature enabled the returned Foo
object isn't supposed to be null because it is a non-nullable type.
If I wanted it to be nullable I'd specify it has a Foo?
So why is the compiler saying it's a nullable variable?
Thank you
Here is a screenshot of what I'm describing here. When you hover your mouse over the foo
variable
Upvotes: 9
Views: 1742
Reputation: 42235
In the original implementation, foo
would have been inferred as a Foo
.
However, people complained that this got in the way of things like:
string? GetThing() => ...
var result = "";
if (condition)
{
result = GetThing();
}
If result
is inferred as a string
, then the result = GetThing()
line causes a warning: GetThing()
returns a string?
, and there's a warning if you try and assign a string?
to a string
.
The solution was to infer result
as a string?
, but the compiler knows that it's currently not null (its "flow state" is "NotNull").
This means that:
string? GetThing() => ...
var result = "";
// No warning, as the compiler knows that result isn't null
int l1 = result.Length;
if (condition)
{
result = GetThing();
}
// Warning: the compiler knows 'result' might have been re-assigned
int l2 = result.Length;
For other examples of the flow state at work, see things like:
string? result = GetString();
if (result == null)
throw new Exception();
// No warning: the compiler knows that result can't be null here: if it was,
// the exception above would have been thrown
int l1 = result.Length;
string? result = GetString();
// Warning: result might be null
int l1 = result.Length;
// No warning: the compiler knows that result can't be null here: if it was,
// the line above would have thrown
int l2 = result.Length;
string result = "hello";
if (result == null)
Console.WriteLine("NULL!");
// Warning: because we checked for null above, the compiler assumes that we
// know something that it doesn't, and so result might be null.
int l1 = result.Length;
Upvotes: 10
Reputation: 3539
Check out the specification on nullable reference types. It states that var
infers an annotated type for reference types.
The part under the heading nullable implicitly typed local variables reads:
var infers an annotated type for reference types. For instance, in var s = ""; the var is inferred as string?.
Upvotes: 0