Сообщение Идея для новой версии C# от 17.12.2025 13:31
Изменено 17.12.2025 20:25 VladD2
Идея для новой версии C#
Рефачу сейчас библиотеку, в которой создается огромный граф. Перевожу его на поддержку #nullable enable.
И понимаю, что современная поддержка nullable в C# очень неполноценная. Большинство ссылок в законченном графе не нулабельные, но код его построения императивный и в нем просто невозможно без хаков проинициализировать свойства во время создания объектов. Приходится прибегать к вот такому хаку:
Вот собственно стало очевидно, что система нулабельности для этого не приспособлена.
Предлагаю расширить C# блоком инициализации, внутри которого не будет проверяться нулабельность, а все проверки будут осуществляться будут осуществляться при выходк из него:
Компилятор осуществляет проверки нулабельности только при выходе из блока (в конце или по return).
Предполагается, что можно объединять несколько инициализаций:
Так же предполагается, что синтаксис аналогичен using, т.е. если не указаны круглые скобки, блоком является вложенная область видимости.
И понимаю, что современная поддержка nullable в C# очень неполноценная. Большинство ссылок в законченном графе не нулабельные, но код его построения императивный и в нем просто невозможно без хаков проинициализировать свойства во время создания объектов. Приходится прибегать к вот такому хаку:
var obj1 = new SomeType1() { Prop1 = null! };
var obj2 = new SomeType2() { Prop1 = obj1 };
obj1.Prop1 = obj2;Вот собственно стало очевидно, что система нулабельности для этого не приспособлена.
Предлагаю расширить C# блоком инициализации, внутри которого не будет проверяться нулабельность, а все проверки будут осуществляться будут осуществляться при выходк из него:
init (var obj1 = new SomeType1()) // не ругается на то, что obj1.Prop1 не заполнен
{
var obj2 = new SomeType2() { Prop1 = obj1 };
if (condition)
return; // компилятора ругается, так как к этому моменту obj1.Prop1 не проинициализирован.
obj1.Prop1 = obj2; // obj1.Prop1 считается проинициализированным.
}Компилятор осуществляет проверки нулабельности только при выходе из блока (в конце или по return).
Предполагается, что можно объединять несколько инициализаций:
init (var obj1 = new SomeType1())
init (var obj2 = new SomeType1())
init (var obj3 = new SomeType1())
{
obj1.Prop1 = obj2;
obj2.Prop1 = obj3;
obj3.Prop1 = obj1;
}Так же предполагается, что синтаксис аналогичен using, т.е. если не указаны круглые скобки, блоком является вложенная область видимости.
void Foo()
{
init var obj1 = new SomeType1();
init var obj2 = new SomeType1();
init var obj3 = new SomeType1();
obj1.Prop1 = obj2;
obj2.Prop1 = obj3;
obj3.Prop1 = obj1;
}Идея для новой версии C#
Рефачу сейчас библиотеку, в которой создается огромный граф. Перевожу его на поддержку #nullable enable.
И понимаю, что современная поддержка nullable в C# очень неполноценная. Большинство ссылок в законченном графе не нулабельные, но код его построения императивный и в нем просто невозможно без хаков проинициализировать свойства во время создания объектов. Приходится прибегать к вот такому хаку:
Вот собственно стало очевидно, что система нулабельности для этого не приспособлена.
Предлагаю расширить C# блоком инициализации, внутри которого не будет проверяться нулабельность, а все проверки будут осуществляться при выходе из него:
Компилятор осуществляет проверки нулабельности только при выходе из блока (в конце или по return).
Предполагается, что можно объединять несколько инициализаций:
Так же предполагается, что синтаксис аналогичен using, т.е. если не указаны круглые скобки, блоком является вложенная область видимости.
И понимаю, что современная поддержка nullable в C# очень неполноценная. Большинство ссылок в законченном графе не нулабельные, но код его построения императивный и в нем просто невозможно без хаков проинициализировать свойства во время создания объектов. Приходится прибегать к вот такому хаку:
var obj1 = new SomeType1() { Prop1 = null! };
var obj2 = new SomeType2() { Prop1 = obj1 };
obj1.Prop1 = obj2;Вот собственно стало очевидно, что система нулабельности для этого не приспособлена.
Предлагаю расширить C# блоком инициализации, внутри которого не будет проверяться нулабельность, а все проверки будут осуществляться при выходе из него:
init (var obj1 = new SomeType1()) // не ругается на то, что obj1.Prop1 не заполнен
{
var obj2 = new SomeType2() { Prop1 = obj1 };
if (condition)
return; // компилятора ругается, так как к этому моменту obj1.Prop1 не проинициализирован.
obj1.Prop1 = obj2; // obj1.Prop1 считается проинициализированным.
}Компилятор осуществляет проверки нулабельности только при выходе из блока (в конце или по return).
Предполагается, что можно объединять несколько инициализаций:
init (var obj1 = new SomeType1())
init (var obj2 = new SomeType1())
init (var obj3 = new SomeType1())
{
obj1.Prop1 = obj2;
obj2.Prop1 = obj3;
obj3.Prop1 = obj1;
}Так же предполагается, что синтаксис аналогичен using, т.е. если не указаны круглые скобки, блоком является вложенная область видимости.
void Foo()
{
init var obj1 = new SomeType1();
init var obj2 = new SomeType1();
init var obj3 = new SomeType1();
obj1.Prop1 = obj2;
obj2.Prop1 = obj3;
obj3.Prop1 = obj1;
}