С# 10 - есть ли способ заставить "var" определить переменную как ненулевую?

Когда я пишу это заявление:

Var x = new ClassName();

X неявно печатается как ClassName?. То есть, поскольку ClassName является ссылочным типом, неявные присваивания с использованием var автоматически определяются как обнуляемые (даже когда я предоставляю ненулевой экземпляр и никогда его не изменяю).

Мой вопрос: есть ли способ сделать ненулевое значение по умолчанию при использовании ключевого слова «var»?

Я знаю об этом вопросе и связанной с ним информации: Почему Visual Studio вводит недавно созданный массив как Nullable?

Все классы неявно допускают значение NULL.

Joel Coehoorn 10.01.2023 23:32

Согласно документации, это невозможно . В нем говорится: «Однако любые неявно типизированные локальные переменные (объявленные с использованием var) являются ссылочными типами, допускающими значение NULL». Казалось бы, это находится в прямом конфликте с нормальным выводом типа var, но то, как был разработан язык, не упрощало использование var с ссылочными типами, допускающими значение NULL.

NetMage 10.01.2023 23:36

Обратите внимание, что в последних версиях C# (начиная с 9) new обрабатывает целевую типизацию, так что вы можете сделать ClassName x = new();

NetMage 10.01.2023 23:49

Или вы можете отключить типы, допускающие значение NULL, во всем проекте, изменив <Nullable>enable</Nullable> на <Nullable>disable</Nullable>. Вы также можете изменить допустимость значений NULL в своем коде, поместив #nullable disable ... #nullable enable вокруг своих свойств.

Codingwiz 10.01.2023 23:53

'var' не проблема. Если вы используете var с ненулевым типом (например, dateTime), вы обнаружите, что получаете ошибки компиляции (var foo = DateTime.Now;foo=null;). Проблема в том, что классы по умолчанию имеют значение NULL. Каков ваш вариант использования этой функции? могут быть обходные пути, такие как класс NonNullable<T> или что-то в этом роде.

The Lemon 11.01.2023 00:22

@TheLemon - на самом деле то, что я ищу, является эквивалентом JS / TS const x = или F# let x = - семантический способ объявить, что этот идентификатор постоянно привязан к первоначально установленному значению (и, таким образом, если начальное значение не равно нулю, идентификатор тоже никогда не будет). (Я понимаю, что var по-прежнему позволяет изменять значение, но я хочу, по крайней мере, установить, что оно никогда не должно быть установлено равным нулю.)

Overlord Zurg 11.01.2023 18:54
Конечные и Readonly классы в PHP
Конечные и Readonly классы в PHP
В прошлом, когда вы не хотели, чтобы другие классы расширяли определенный класс, вы могли пометить его как final.
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
Если вы уже умеете работать с React, создание мобильных приложений для iOS и Android - это новое приключение, в котором вы сможете применить свои...
БЭМ: Конвенция об именовании CSS
БЭМ: Конвенция об именовании CSS
Я часто вижу беспорядочный код CSS, особенно если проект большой. Кроме того, я совершал эту ошибку в профессиональных или личных проектах и...
Революционная веб-разработка ServiceNow
Революционная веб-разработка ServiceNow
В быстро развивающемся мире веб-разработки ServiceNow для достижения успеха крайне важно оставаться на вершине последних тенденций и технологий. По...
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Заголовок веб-страницы играет наиболее важную роль в SEO, он помогает поисковой системе понять, о чем ваш сайт.
Конфигурация Jest в angular
Конфигурация Jest в angular
В этой статье я рассказываю обо всех необходимых шагах, которые нужно выполнить при настройке jest в angular.
1
6
104
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий
есть ли способ сделать ненулевое значение по умолчанию при использовании ключевого слова "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() кажется наиболее кратким способом определить переменную как необнуляемую.
Overlord Zurg 11.01.2023 18:57

(отвечая на вариант использования в вашем комментарии больше, чем на вопрос). Если вам нужен ненулевой декоратор только для чтения (предположительно, на уровне метода, в противном случае вы могли бы просто использовать объявление «только для чтения»), вы можете создать универсальный класс с функциональностью, которая вам нужна. Это не совсем альтернатива «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

    }
}

Другие вопросы по теме