Информация об изменениях

Сообщение Идея для новой версии C# от 17.12.2025 13:31

Изменено 17.12.2025 20:25 VladD2

Идея для новой версии C#
Рефачу сейчас библиотеку, в которой создается огромный граф. Перевожу его на поддержку #nullable enable.

И понимаю, что современная поддержка 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# очень неполноценная. Большинство ссылок в законченном графе не нулабельные, но код его построения императивный и в нем просто невозможно без хаков проинициализировать свойства во время создания объектов. Приходится прибегать к вот такому хаку:
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;
}