Когда я пишу это заявление:
Var x = new ClassName();
X неявно печатается как ClassName?. То есть, поскольку ClassName является ссылочным типом, неявные присваивания с использованием var автоматически определяются как обнуляемые (даже когда я предоставляю ненулевой экземпляр и никогда его не изменяю).
Мой вопрос: есть ли способ сделать ненулевое значение по умолчанию при использовании ключевого слова «var»?
Я знаю об этом вопросе и связанной с ним информации: Почему Visual Studio вводит недавно созданный массив как Nullable?
Согласно документации, это невозможно . В нем говорится: «Однако любые неявно типизированные локальные переменные (объявленные с использованием var) являются ссылочными типами, допускающими значение NULL». Казалось бы, это находится в прямом конфликте с нормальным выводом типа var, но то, как был разработан язык, не упрощало использование var с ссылочными типами, допускающими значение NULL.
Обратите внимание, что в последних версиях C# (начиная с 9) new обрабатывает целевую типизацию, так что вы можете сделать ClassName x = new();
Или вы можете отключить типы, допускающие значение NULL, во всем проекте, изменив <Nullable>enable</Nullable> на <Nullable>disable</Nullable>. Вы также можете изменить допустимость значений NULL в своем коде, поместив #nullable disable ... #nullable enable вокруг своих свойств.
'var' не проблема. Если вы используете var с ненулевым типом (например, dateTime), вы обнаружите, что получаете ошибки компиляции (var foo = DateTime.Now;foo=null;). Проблема в том, что классы по умолчанию имеют значение NULL. Каков ваш вариант использования этой функции? могут быть обходные пути, такие как класс NonNullable<T> или что-то в этом роде.
@TheLemon - на самом деле то, что я ищу, является эквивалентом JS / TS const x = или F# let x = - семантический способ объявить, что этот идентификатор постоянно привязан к первоначально установленному значению (и, таким образом, если начальное значение не равно нулю, идентификатор тоже никогда не будет). (Я понимаю, что var по-прежнему позволяет изменять значение, но я хочу, по крайней мере, установить, что оно никогда не должно быть установлено равным нулю.)
есть ли способ сделать ненулевое значение по умолчанию при использовании ключевого слова "var"
Нет, как указано в документации - var всегда подразумевает нулевой ссылочный тип:
Когда var используется с включенными ссылочными типами, допускающими значение NULL, он всегда подразумевает ссылочный тип, допускающий значение NULL, даже если тип выражения не допускает значение NULL. Анализ нулевого состояния компилятора защищает от разыменования потенциального нулевого значения. Если переменной никогда не будет присвоено выражение, которое может быть нулевым, компилятор не выдаст никаких предупреждений. Если вы присваиваете переменной выражение, которое может быть нулевым, вы должны проверить, что оно не является нулевым, прежде чем разыменовывать его, чтобы избежать каких-либо предупреждений.
Но анализ нулевого состояния может определить, действительно ли переменная не является нулевой, и не выдавать предупреждений в довольно многих случаях (отсюда часть с акцентом в цитате):
public class C
{
public string M(string? j) {
var foo = "";
var bar = j;
// return foo; // no warning
return bar; // warning
}
}
Демо
Если по какой-то причине вам по-прежнему нужен явно необнуляемый тип, вы можете обойти это с помощью целевых типизированных новых выражений в некоторых случаях:
MyClass x = new();
Также вы можете рассмотреть возможность отключения ссылочных типов, допускающих значение null (локально или для всего проекта), или использования оператора, не допускающего null (!).
MyClass x = new()
кажется наиболее кратким способом определить переменную как необнуляемую.
(отвечая на вариант использования в вашем комментарии больше, чем на вопрос). Если вам нужен ненулевой декоратор только для чтения (предположительно, на уровне метода, в противном случае вы могли бы просто использовать объявление «только для чтения»), вы можете создать универсальный класс с функциональностью, которая вам нужна. Это не совсем альтернатива «var», но в какой-то степени она подойдет для вашего варианта использования.
public class ReadOnly<T>
{
private T _value;
public T value { get { return _value; } }
public ReadOnly(T initialValue)
{
if (initialValue == null)
throw new ArgumentException("value must be non-null");
_value = initialValue;
}
public static implicit operator T(ReadOnly<T> readOnly)
{
return readOnly.value;
}
}
public class Foo {
public void Bar() {
var myReadonlyFoo = new ReadOnly<Foo>(this);
myReadonlyFoo.value = this;//compile error
var tempVar = myReadonlyFoo.value;//this works fine
myReadonlyFoo.value.Bar();//this works fine, but will crash the app lol
Foo test = myReadonlyFoo; //with some implicit conversion for the fun of it
}
}
Все классы неявно допускают значение NULL.