C# [Proposal] init block for safe initialization of complex
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.12.25 14:12
Оценка: 5 (1) +1
https://github.com/dotnet/csharplang/discussions/9903

Прошу поддержать лайком по ссылке (на гитхебе). Ну и приветствуются замечания и предложения.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 23.12.2025 15:26 VladD2 . Предыдущая версия .
Re: C# [Proposal] init block for safe initialization of comp
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.12.25 15:26
Оценка: :)
Здравствуйте, VladD2, Вы писали:

VD>https://github.com/dotnet/csharplang/discussions/9903


VD>Прошу поддержать лайком. Ну и приветствуются замечания и предложения.


Народ! Лайки нужны не здесь, а по ссылке.

Да и даже не лайки, а поддержка. Там есть такая стрелочка вверх. Вот её нужно пржать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 30.12.2025 20:29 VladD2 . Предыдущая версия .
Re: C# [Proposal] init block for safe initialization of complex
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 23.12.25 15:52
Оценка:
Здравствуйте, VladD2, Вы писали:

А у Node2.Next будет null?

Не проще ли инициализировать EmptyNode у которого будут ссылки на себя

и сделать приватный конструктор типа
this.Next = this;
this.Previous = this;

Ну и делать проверку на EmptyNode
и солнце б утром не вставало, когда бы не было меня
Re[2]: C# [Proposal] init block for safe initialization of complex objects graph
От: rameel https://github.com/rsdn/CodeJam
Дата: 24.12.25 03:55
Оценка: 55 (1)
Здравствуйте, VladD2, Вы писали:

VD>Народ! Лайки нужны не здесь, а по ссылке.


Там в первую очередь проголосовал
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[2]: C# [Proposal] init block for safe initialization of complex
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.12.25 06:10
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Ну и делать проверку на EmptyNode

Это профанация идеи. Смысл not null — не в том, чтобы не получать NRE, а в том, чтобы иметь семантические гарантии.
EmptyNode ничуть не лучше null: во всём коде нужно делать проверки, что по ссылке — настоящая нода, а не эрзац.
Null Object Pattern работает тогда, когда у нас таки есть какой-то "нейтральный" объект, который может выступать в роли "заглушки". Ну, там, пустая строка вместо null-строки позволяет нам брать у неё длину, конкатенировать и т.п. вместо паники/исключения/segfault.
А non-nullability — это специальный инвариант, гарантирующий нетривиальную инициализацию.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: C# [Proposal] init block for safe initialization of complex
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 24.12.25 07:42
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>>Ну и делать проверку на EmptyNode

S>Это профанация идеи. Смысл not null — не в том, чтобы не получать NRE, а в том, чтобы иметь семантические гарантии.
S>EmptyNode ничуть не лучше null: во всём коде нужно делать проверки, что по ссылке — настоящая нода, а не эрзац.
S>Null Object Pattern работает тогда, когда у нас таки есть какой-то "нейтральный" объект, который может выступать в роли "заглушки". Ну, там, пустая строка вместо null-строки позволяет нам брать у неё длину, конкатенировать и т.п. вместо паники/исключения/segfault.
S>А non-nullability — это специальный инвариант, гарантирующий нетривиальную инициализацию.

Угу,

А у Node2.Next будет null?


Суть EmptyNode это как раз и есть аналог пустой строки. Ты можешь вызвать методы, свойства. Просто они будут ссылаться на соответствующие Empty.
То есть каждый класс должен создавать такой объект. При этом он должен быть иммутабельным.
и солнце б утром не вставало, когда бы не было меня
Re[4]: C# [Proposal] init block for safe initialization of complex
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.12.25 09:58
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Суть EmptyNode это как раз и есть аналог пустой строки. Ты можешь вызвать методы, свойства. Просто они будут ссылаться на соответствующие Empty.

S> То есть каждый класс должен создавать такой объект. При этом он должен быть иммутабельным.

Зачем вы объясняете мне то же самое, что я вам объяснил?
Null object pattern не решает поставленную задачу.
Вот представьте, что у вас есть департаменты, в которых работают сотрудники.
И есть инвариант, что у каждого департамента обязан быть указан руководитель, а у каждого сотрудника — департамент.
Не в том, чтобы они были "не null"! А в том, что не может быть департамента без руководителя, и сотрудника вне департамента.

Минимальная корректная топология — это department1.Manager = employee1, и employee1.Department = department1.
Нет никакого "EmptyDepatment" — кто у него будет руководителем? И нет никакого EmptyEmployee — в каком департаменте он будет работать?
Даже если мы возьмём и "как-то" породим эту минимальную пару, обойдя ограничение языка, нам это никак не поможет.
Потому что мы сможем сконструировать, например, департамент departmentX = new Department() { Manager = EmptyEmployee}.
И этот департамент с точки зрения бизнес-логики ничуть не лучше, чем департамент, у которого .Manager == null.
Не может "никто" быть руководителем департамента — бизнес-логика такая!
Мы, собственно, хотим убрать изо всего кода бесчисленных проверок вида if(dept.Manager == null) log.Warning("Обнаружен департамент без руководителя — не можем подготовить приказ о начислении премий") else RegisterBonus(dept.Manager). Всё, что вы можете добиться с NullObject — это замены этого кода на if(dept.Manager == EmptyEmployee) log.Warning("Обнаружен департамент без руководителя — не можем подготовить приказ о начислении премий") else RegisterBonus(dept.Manager)
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: C# [Proposal] init block for safe initialization of complex
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 24.12.25 10:11
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>> Суть EmptyNode это как раз и есть аналог пустой строки. Ты можешь вызвать методы, свойства. Просто они будут ссылаться на соответствующие Empty.

S>> То есть каждый класс должен создавать такой объект. При этом он должен быть иммутабельным.

S>Зачем вы объясняете мне то же самое, что я вам объяснил?

S>Null object pattern не решает поставленную задачу.
S>Вот представьте, что у вас есть департаменты, в которых работают сотрудники.
S>И есть инвариант, что у каждого департамента обязан быть указан руководитель, а у каждого сотрудника — департамент.
S>Не в том, чтобы они были "не null"! А в том, что не может быть департамента без руководителя, и сотрудника вне департамента.

S>Минимальная корректная топология — это department1.Manager = employee1, и employee1.Department = department1.

S>Нет никакого "EmptyDepatment" — кто у него будет руководителем? И нет никакого EmptyEmployee — в каком департаменте он будет работать?
S>Даже если мы возьмём и "как-то" породим эту минимальную пару, обойдя ограничение языка, нам это никак не поможет.
S>Потому что мы сможем сконструировать, например, департамент departmentX = new Department() { Manager = EmptyEmployee}.
S>И этот департамент с точки зрения бизнес-логики ничуть не лучше, чем департамент, у которого .Manager == null.
S>Не может "никто" быть руководителем департамента — бизнес-логика такая!
S>Мы, собственно, хотим убрать изо всего кода бесчисленных проверок вида if(dept.Manager == null) log.Warning("Обнаружен департамент без руководителя — не можем подготовить приказ о начислении премий") else RegisterBonus(dept.Manager). Всё, что вы можете добиться с NullObject — это замены этого кода на if(dept.Manager == EmptyEmployee) log.Warning("Обнаружен департамент без руководителя — не можем подготовить приказ о начислении премий") else RegisterBonus(dept.Manager)


Sinclair не читатель. Еще раз какой узел следующий для последнего узла?
Empty нужны для обозначения, что этот объект дефолтный. У него можно вызвать методы, получить свойства.
Так же его нельзя присваивать свойствам которые должны иметь недефолтные значения и это проверяется в сеттерах или конструкторах.
Можно помечать такие свойства атрибутами и проверять через SG
Все тоже, что и со string.Empty
и солнце б утром не вставало, когда бы не было меня
Re[6]: C# [Proposal] init block for safe initialization of complex
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.12.25 10:48
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Sinclair не читатель.

Нет, это Serginio1 не читатель.

S>Еще раз какой узел следующий для последнего узла?

Зависит от используемых инвариантов. Например, у "последнего" узла следующим может быть null.
Это позволяет, к примеру, делать простое итерирование:
public static IEnumerable<Node> EnumerateForward(Node? list) {
  while (list) {
    yield return list;
    list = list.Next;
  }
}

Это работает, если для нас такая топология является нормальной. В такой топологии никакой пользы от EmptyNode нету.

Если нет, то у нас совсем другой инвариант — за нодой должна идти валидная нода. И в ней тоже нет никакой пользы от EmptyNode.

S> Empty нужны для обозначения, что этот объект дефолтный. У него можно вызвать методы, получить свойства.

Я вам в третий раз пишу: дефолтные объекты не помогают решить проблему, сформулированную Владом. У него проблема не в том, что у null нельзя вызывать методы или получать свойства.
S>Так же его нельзя присваивать свойствам которые должны иметь недефолтные значения и это проверяется в сеттерах или конструкторах.
Прекрасно. Попробуйте запретить присваивание EmptyNode в сеттерах Next и Previous. Получите нерабочий код.
И вообще — вы переносите проверку в рантайм, а смысл не в том, чтобы неверный код падал при исполнении. Он и так падает при исполнении.
И делать проверки на null в конструкторе мы умели ещё четыре версии языка назад:
this.next = next ?? throw new ArgumentNullException(nameof(next))


S>Можно помечать такие свойства атрибутами и проверять через SG

Это по-прежнему не решает исходную задачу.
S> Все тоже, что и со string.Empty
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: C# [Proposal] init block for safe initialization of complex
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 24.12.25 11:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>Sinclair не читатель.

S>Нет, это Serginio1 не читатель.

S>>Еще раз какой узел следующий для последнего узла?

S>Зависит от используемых инвариантов. Например, у "последнего" узла следующим может быть null.
S>Это позволяет, к примеру, делать простое итерирование:
S>
S>public static IEnumerable<Node> EnumerateForward(Node? list) {
S>  while (list) {
S>    yield return list;
S>    list = list.Next;
S>  }
S>}
S>

S>Это работает, если для нас такая топология является нормальной. В такой топологии никакой пользы от EmptyNode нету.


угу с null ты получишь ошибку на null
и чем (list!=null) лучше
while (!list.IsEmpty)





S>Если нет, то у нас совсем другой инвариант — за нодой должна идти валидная нода. И в ней тоже нет никакой пользы от EmptyNode.


Есть такая же польза как и у string.Empty. Позволяет работать с методами и свойствами.

S>> Empty нужны для обозначения, что этот объект дефолтный. У него можно вызвать методы, получить свойства.

S>Я вам в третий раз пишу: дефолтные объекты не помогают решить проблему, сформулированную Владом. У него проблема не в том, что у null нельзя вызывать методы или получать свойства.

У него проблема с отложенной инициализацией. Но и в его примере для последнего узла Next будет null

S>>Так же его нельзя присваивать свойствам которые должны иметь недефолтные значения и это проверяется в сеттерах или конструкторах.

S>Прекрасно. Попробуйте запретить присваивание EmptyNode в сеттерах Next и Previous. Получите нерабочий код.


S>И вообще — вы переносите проверку в рантайм, а смысл не в том, чтобы неверный код падал при исполнении. Он и так падает при исполнении.

S>И делать проверки на null в конструкторе мы умели ещё четыре версии языка назад:
S>
S>this.next = next ?? throw new ArgumentNullException(nameof(next))
S>


Ограничение может быть не только на Empty, но и по другим свойствам. И вот Empty как раз хорош.

S>>Можно помечать такие свойства атрибутами и проверять через SG

S>Это по-прежнему не решает исходную задачу.
S>> Все тоже, что и со string.Empty
S>

Исходная задача это заменить null и добавить проверку на присваивание!
Это можно сделать и добавив свои анализаторы отключив родные.
Но в итоге и это не решает проблему ибо null то остается!
и солнце б утром не вставало, когда бы не было меня
Re: C# [Proposal] init block for safe initialization of complex
От: sergii.p  
Дата: 24.12.25 14:27
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>https://github.com/dotnet/csharplang/discussions/9903


init (var obj1 = new SomeType1(), var obj2 = new SomeType2())
{
obj1.Prop = obj2;
obj2.Prop = obj1;
// Local functions are allowed
void Connect() => obj1.Child = obj2;
Connect();
} // Compiler checks here that all non-nullable members are initialized

почему только локальные функции? Как бы чего не вышло? Установка свойства уже может вызывать кучу логики вполне себе внешней.

Да и пока не очень понял, так ли уж оно сильно надо? Например, чем плохо использовать обычные reference types? Или использовать нормальные Optional (которых правда в шарпе нет, но их можно подтянуть извне). Н-р почти во всех языках Next будет Optional/Maybe.
Вообще motivation часть как-то не раскрыта.
Re[8]: C# [Proposal] init block for safe initialization of complex
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.12.25 16:30
Оценка: +1
Здравствуйте, Serginio1, Вы писали:

S>угу с null ты получишь ошибку на null

И по крайней мере программа детерминированно упадёт. А с EmptyNode у нас может быть половина узлов в списке фиктивными, и программа будет делать вид, что работает. Вот только все метрики типа длин путей будут фуфельными.

S> и чем (list!=null) лучше

S>
S>while (!list.IsEmpty)
S>

Обратный вопрос: чем list.IsEmpty лучше, чем list == null?

S> Есть такая же польза как и у string.Empty. Позволяет работать с методами и свойствами.

Нет никакой пользы. Сосредоточьтесь и постарайтесь писать по делу, а не абстрактную чушь.

S> У него проблема с отложенной инициализацией. Но и в его примере для последнего узла Next будет null

И это должен отловить компилятор!

S> Ограничение может быть не только на Empty, но и по другим свойствам. И вот Empty как раз хорош.

Опять вы пишете что-то бессвязное.

S> Исходная задача это заменить null и добавить проверку на присваивание!

Нет. Исходная задача — это гарантировать, что при обработке графа никогда не встретится непроинициализированный узел
S> Это можно сделать и добавив свои анализаторы отключив родные.
S> Но в итоге и это не решает проблему ибо null то остается!
Ну так вам об этом и говорят.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: C# [Proposal] init block for safe initialization of c
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 24.12.25 17:29
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>Обратный вопрос: чем list.IsEmpty лучше, чем list == null?


Тем, что кой кому не нужен Nullable reference


S>> Исходная задача это заменить null и добавить проверку на присваивание!

S>Нет. Исходная задача — это гарантировать, что при обработке графа никогда не встретится непроинициализированный узел
S>> Это можно сделать и добавив свои анализаторы отключив родные.
S>> Но в итоге и это не решает проблему ибо null то остается!
S>Ну так вам об этом и говорят.

Но в итоге у него код не пройдет проверку! Так как Next для последнего и Previous для первого будет null!
Никто не мешает добавить свой анализатор без изменения языка!
А использование Empty объекта значительно лучше чем null!
и солнце б утром не вставало, когда бы не было меня
Отредактировано 24.12.2025 17:38 Serginio1 . Предыдущая версия . Еще …
Отредактировано 24.12.2025 17:32 Serginio1 . Предыдущая версия .
Re[10]: C# [Proposal] init block for safe initialization of c
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.12.25 02:05
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Тем, что кой кому не нужен Nullable reference

А вам не приходило в голову задуматься: а почему этому кой-кому не нужен Nullable Reference? Если не приходило — перечитайте стартовый пост, там всё написано.

S> Но в итоге у него код не пройдет проверку! Так как Next для последнего и Previous для первого будет null!

Именно это и прекрасно. Компилятор потребует от него добавить инициализацию для этих свойств, и только тогда успокоится. Это и есть статическая гарантия того, что в рантайме он никогда не напорется ни на Null, ни на EmptyNode.
S>Никто не мешает добавить свой анализатор без изменения языка!
Ок, предположим, у нас есть такой анализатор. Накидайте пример пользовательского кода с его применением.

S>А использование Empty объекта значительно лучше чем null!

Нет. Восклицательные знаки аргументом в споре не являются. Повторюсь: я знаком с Null Object Pattern и понимаю не только его преимущества, но и недостатки.
В данной задаче этот паттерн противопоказан как раз тем, что мешает компилятору проверять инициализированность. Потому что понятие "Ссылка на Node, для которой запрещено использование null" в компилятор встроено, а "ссылка на Node, для которой запрещено использование EmptyNode" — нет. Это не Алгол.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: C# [Proposal] init block for safe initialization of complex
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.12.25 02:13
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>почему только локальные функции? Как бы чего не вышло?

Потому, что про нелокальные функции у компилятора нет информации. Я и с локальными-то сомневаюсь, что
Установка свойства уже может вызывать кучу логики вполне себе внешней.

SP>Да и пока не очень понял, так ли уж оно сильно надо? Например, чем плохо использовать обычные reference types?

avoiding unexpected nulls is a huge benefit, particularly in larger codebases where it's harder to keep track of the edge cases where things can be null by yourself

SP>Или использовать нормальные Optional (которых правда в шарпе нет, но их можно подтянуть извне). Н-р почти во всех языках Next будет Optional/Maybe.
Попробуйте переписать пример с использованием Optional. Станет хуже
SP>Вообще motivation часть как-то не раскрыта.
По-моему так вполне внятно раскрыта. Что именно непонятно или вызывает сомнения?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[11]: C# [Proposal] init block for safe initialization of
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 25.12.25 07:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>> Тем, что кой кому не нужен Nullable reference

S> А вам не приходило в голову задуматься: а почему этому кой-кому не нужен Nullable Reference? Если не приходило — перечитайте стартовый пост, там всё написано.

S>> Но в итоге у него код не пройдет проверку! Так как Next для последнего и Previous для первого будет null!

S>Именно это и прекрасно. Компилятор потребует от него добавить инициализацию для этих свойств, и только тогда успокоится. Это и есть статическая гарантия того, что в рантайме он никогда не напорется ни на Null, ни на EmptyNode.
Антон ты прикалываешься? Еще раз

Так как Next для последнего и Previous для первого будет null


Только добавив Empty компилятор и успокоится
S>>Никто не мешает добавить свой анализатор без изменения языка!
S>Ок, предположим, у нас есть такой анализатор. Накидайте пример пользовательского кода с его применением.

#продвинутый nullable enable
        var obj1 = new SomeType1();
       var obj2 = new SomeType2();
obj1.Prop = obj2;
obj2.Prop = obj1;
// Local functions are allowed
void Connect() => obj1.Child = obj2;
Connect();
#продвинутый nullable disable


Ну или
#pragma warning disable продвинутый nullable
#pragma warning restore продвинутый nullable

через наследника DiagnosticAnalyzer
и солнце б утром не вставало, когда бы не было меня
Отредактировано 25.12.2025 10:48 Serginio1 . Предыдущая версия . Еще …
Отредактировано 25.12.2025 10:18 Serginio1 . Предыдущая версия .
Отредактировано 25.12.2025 9:35 Serginio1 . Предыдущая версия .
Re[3]: C# [Proposal] init block for safe initialization of complex
От: sergii.p  
Дата: 25.12.25 10:41
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Потому, что про нелокальные функции у компилятора нет информации.


то есть вызвать нелокальные функции в обработке property.set он может, а в init блоке он их уже не видит? Или может я не понял, что имеется в виду под локальными функциями? Локальные в модуле, классе, функции?

S>Попробуйте переписать пример с использованием Optional. Станет хуже


переписал. Не вижу, что стало хуже

using System;
using System.Collections.Generic;
using Optional;

public class Node<T>
{
    public required T Value { get; set; }
    public Option<Node<T>> Next { get; set; }
    public Option<Node<T>> Previous { get; set; }

    public Node(T value)
    {
        Value = value;
        Next = Option.None<Node<T>>();
        Previous = Option.None<Node<T>>();
    }

    public static Option<Node<T>> Init<T>(IEnumerable<T> values)
    {
        using var enumerator = values.GetEnumerator();
        if (!enumerator.MoveNext())
            return Option.None<Node<T>>();

        var head = new Node<T>(enumerator.Current);
        var current = head;

        while (enumerator.MoveNext())
        {
            var newNode = new Node<T>(enumerator.Current);

            current.Next = Option.Some(newNode);
            newNode.Previous = Option.Some(current);

            current = newNode;
        }

        return Option.Some(head);
    }

    public static IEnumerable<T> TraverseForward<T>(Option<Node<T>> start)
    {
        var current = start;

        while (current.Match(
            some: node =>
            {
                yield return node.Value;
                current = node.Next;
                return true;
            },
            none: () => false
        )) { }
    }
}


S>Что именно непонятно или вызывает сомнения?


ну вот привёл код выше. Чем секция init будет лучше? Позволит писать компактнее — спорно. Безопаснее — да нисколько. В общем motivation должен быть в виде сравнения. Вот у меня был такой workaround, а вот так получается с init блоком. Второй вариант очевидно лучше по следующим причинам ... Сейчас лично мне совсем не очевидно.
Re[12]: C# [Proposal] init block for safe initialization of
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.12.25 15:18
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Антон ты прикалываешься? Еще раз

S>

S>Так как Next для последнего и Previous для первого будет null

Ок. Я, наверное, плохо объясняю очевидные лично мне вещи.
Давайте помедленнее. Вот у нас класс ноды с обязательными ссылками:

class Node
{
    public required Node Next { get; set; }
    public required Node Previous { get; set; }
    public string Name {get; init;}
    public Node(string name) => Name = name;
}

public static IEnumerable<string> Iterate(Node start) {
  var current = start;
  do { 
    yield return current.Name; 
    current = current.Next;
  } while(current != start);
}


Существующий компилятор, попытка 1:
var node1 = new Node("Hello"); 
var node2 = new Node("World") { Next = node1, Previous = node1 }; 
foreach(var n in Iterate(node1))
  Console.WriteLine(n);

Compile time error: Required member 'Program.Node.Next' must be set in the object initializer or attribute constructor.
Compile time error: Required member 'Program.Node.Previous' must be set in the object initializer or attribute constructor.


попытка 2:
var node1 = new Node("Hello") { Next = null!, Previous = null! }; 
var node2 = new Node("World") { Next = node1, Previous = node1) }; 
node1.Previous = node2;
foreach(var n in Iterate(node1)
  Console.WriteLine(n);

Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.

Попробуйте решить проблему при помощи EmptyNode.


S>
S>#продвинутый nullable enable
S>        var obj1 = new SomeType1();
S>       var obj2 = new SomeType2();
S>obj1.Prop = obj2;
S>obj2.Prop = obj1;
S>// Local functions are allowed
S>void Connect() => obj1.Child = obj2;
S>Connect();
S>#продвинутый nullable disable
S>

Ничего не получится. Если Prop — non-nullable required, то этот код не скомпилируется. Если он объявлен как nullable — то любой случайный дятел сможет его занулить после строчки #продвинутй nullable disable.
Ещё идеи есть?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[13]: C# [Proposal] init block for safe initialization of
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 25.12.25 15:27
Оценка:
Здравствуйте, Sinclair, Вы писали:

решить проблему при помощи EmptyNode.


S>>
S>>#продвинутый nullable enable
S>>        var obj1 = new SomeType1();
S>>       var obj2 = new SomeType2();
S>>obj1.Prop = obj2;
S>>obj2.Prop = obj1;
S>>// Local functions are allowed
S>>void Connect() => obj1.Child = obj2;
S>>Connect();
S>>#продвинутый nullable disable
S>>

S>Ничего не получится. Если Prop — non-nullable required, то этот код не скомпилируется. Если он объявлен как nullable — то любой случайный дятел сможет его занулить после строчки #продвинутй nullable disable.
S>Ещё идеи есть?

Еще раз #продвинутый nullable enable это анализатор проверки установки свойств
Он будет выдавать ошибку если не установлены все свойства obj1 и obj2
Написать свой анализатор кода не проблема.
Разумеется основная проверка non-nullable required будет отключена, так за проверку будет отвечать #продвинутый nullable enable

Если нет отмены то можно и так

 #nullable disable
 #продвинутй nullable enable
 код c проверкой на присваивание всем полям не null значений
 #продвинутй nullable disable
 #nullable enable


Это намного лучше чем городить новый язык, так как может применяться ко всем версиям языка начиная C# 8.0
и солнце б утром не вставало, когда бы не было меня
Отредактировано 25.12.2025 19:56 Serginio1 . Предыдущая версия . Еще …
Отредактировано 25.12.2025 19:53 Serginio1 . Предыдущая версия .
Re[13]: C# [Proposal] init block for safe initialization of
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 25.12.25 15:40
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>попытка 2:

S>
S>var node1 = new Node("Hello") { Next = null!, Previous = null! }; 
S>var node2 = new Node("World") { Next = node1, Previous = node1) }; 
S>node1.Previous = node2;
S>foreach(var n in Iterate(node1)
S>  Console.WriteLine(n);
S>

S>Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.

S>Попробуйте решить проблему при помощи EmptyNode.



var node1 = new Node("Hello") { Next = Node.EmptyNode, Previous = Node.EmptyNode }; 
var node2 = new Node("World") { Next = node1, Previous = Node.EmptyNode) }; 
node1.Previous = node2;
foreach(var n in Iterate(node1)
Console.WriteLine(n);


И никаких System.NullReferenceException
и солнце б утром не вставало, когда бы не было меня
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.