Ссылочный тип, не допускающий значения NULL: почему мой объект считается компилятором допускающим значение NULL? - PullRequest
3 голосов
/ 19 июня 2020

У меня есть проект, в котором я включил новую функцию ссылочного типа, допускающего значение NULL

 <Nullable>enable</Nullable>

Теперь давайте рассмотрим этот код

public class Foo  {    }

var foo = new Foo();

Компилятор считает переменная foo должна иметь значение NULL (Foo?). Это почему? Я не понимаю.

Теперь с включенной функцией ссылочного типа, допускающей значение NULL, возвращаемый объект Foo не должен иметь значение NULL, потому что это тип, не допускающий значения NULL.

Если бы я хотел, чтобы он допускал значение NULL, я бы указал, что он имеет Foo?

Так почему компилятор говорит, что это переменная, допускающая значение NULL?

Спасибо

РЕДАКТИРОВАТЬ

Вот скриншот того, что я здесь описываю. При наведении курсора мыши на foo переменную

Hover the foo variable

Ответы [ 2 ]

3 голосов
/ 19 июня 2020

В исходной реализации foo было бы выведено как Foo.

Однако люди жаловались, что это мешает таким вещам, как:

string? GetThing() => ...

var result = "";
if (condition)
{
    result = GetThing();
}

Если result выводится как string, тогда строка result = GetThing() вызывает предупреждение: GetThing() возвращает string?, и появляется предупреждение, если вы пытаетесь присвоить string? string.

Решение заключалось в том, чтобы вывести result как string?, но компилятор знает, что в настоящее время он не равен нулю (его «состояние потока» - «NotNull»).

Это означает, что :

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; 

Для других примеров состояния потока в работе см. Такие вещи, как:

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;
0 голосов
/ 19 июня 2020

Ознакомьтесь со спецификацией ссылочных типов , допускающих значение NULL. В нем указано, что var определяет аннотированный тип для ссылочных типов.

Часть под заголовком неявно типизированные локальные переменные, допускающие значение NULL, читает:

var означает, что аннотированный тип для ссылочных типов. Например, в var s = ""; var выводится как строка?.

...