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

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

var x = new ClassName();

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

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

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

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

Joel Coehoorn 10.01.2023 23:32

Обратите внимание, что в последних версиях 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
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
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

    }
}

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