Сообщение Re: Идея для новой версии C# от 23.12.2025 12:14
Изменено 23.12.2025 12:24 _FRED_
Re: Идея для новой версии C#
Здравствуйте, VladD2, Вы писали:
VD>Рефачу сейчас библиотеку, в которой создается огромный граф. Перевожу его на поддержку #nullable enable.
VD>И понимаю, что современная поддержка nullable в C# очень неполноценная. Большинство ссылок в законченном графе не нулабельные, но код его построения императивный и в нем просто невозможно без хаков проинициализировать свойства во время создания объектов. Приходится прибегать к вот такому хаку:
Можешь показать, как Prop1 и Prop2 объявлены? По идее уже в их объявлении у тебя может быть засада с
VD>Вот собственно стало очевидно, что система нулабельности для этого не приспособлена.
VD>Предлагаю расширить C# блоком инициализации, внутри которого не будет проверяться нулабельность, а все проверки будут осуществляться при выходе из него:
А #nullable disable и #nullable restore (здесь) не подходят?
VD>Рефачу сейчас библиотеку, в которой создается огромный граф. Перевожу его на поддержку #nullable enable.
VD>И понимаю, что современная поддержка nullable в C# очень неполноценная. Большинство ссылок в законченном графе не нулабельные, но код его построения императивный и в нем просто невозможно без хаков проинициализировать свойства во время создания объектов. Приходится прибегать к вот такому хаку:
VD>var obj1 = new SomeType1() { Prop1 = null! };
VD>var obj2 = new SomeType2() { Prop1 = obj1 };
VD>obj1.Prop1 = obj2;Можешь показать, как Prop1 и Prop2 объявлены? По идее уже в их объявлении у тебя может быть засада с
public SomeType2 Prop { get; set; } = null!;VD>Вот собственно стало очевидно, что система нулабельности для этого не приспособлена.
VD>Предлагаю расширить C# блоком инициализации, внутри которого не будет проверяться нулабельность, а все проверки будут осуществляться при выходе из него:
VD>init (var obj1 = new SomeType1()) // не ругается на то, что obj1.Prop1 не заполнен
VD>…А #nullable disable и #nullable restore (здесь) не подходят?
#nullable disable
var obj1 = new SomeType1 { Prop = null, }; // No warning here
var obj2 = new SomeType2 { Prop = obj1, };
obj1.Prop = obj2;
#nullable restore
obj1.Prop = GetNullable(); // CS8601 Possible null reference assignment.
static SomeType2? GetNullable() => null;
file sealed class SomeType1 { public SomeType2 Prop { get; set; } = null!; };
file sealed class SomeType2 { public SomeType1 Prop { get; set; } = null!; };Re: Идея для новой версии C#
Здравствуйте, VladD2, Вы писали:
VD>Рефачу сейчас библиотеку, в которой создается огромный граф. Перевожу его на поддержку #nullable enable.
VD>И понимаю, что современная поддержка nullable в C# очень неполноценная. Большинство ссылок в законченном графе не нулабельные, но код его построения императивный и в нем просто невозможно без хаков проинициализировать свойства во время создания объектов. Приходится прибегать к вот такому хаку:
Можешь показать, как Prop1 и Prop2 объявлены? По идее уже в их объявлении у тебя может быть засада с
VD>Вот собственно стало очевидно, что система нулабельности для этого не приспособлена.
VD>Предлагаю расширить C# блоком инициализации, внутри которого не будет проверяться нулабельность, а все проверки будут осуществляться при выходе из него:
А #nullable disable и #nullable restore (здесь) не подходят?
По идее вся засада в том, как объявить подобное свойство, которое должно быть проинициализированно после конструктора / инициализатора?
Я бы попробовал отказаться от null-ов как-то так:
VD>Рефачу сейчас библиотеку, в которой создается огромный граф. Перевожу его на поддержку #nullable enable.
VD>И понимаю, что современная поддержка nullable в C# очень неполноценная. Большинство ссылок в законченном графе не нулабельные, но код его построения императивный и в нем просто невозможно без хаков проинициализировать свойства во время создания объектов. Приходится прибегать к вот такому хаку:
VD>var obj1 = new SomeType1() { Prop1 = null! };
VD>var obj2 = new SomeType2() { Prop1 = obj1 };
VD>obj1.Prop1 = obj2;Можешь показать, как Prop1 и Prop2 объявлены? По идее уже в их объявлении у тебя может быть засада с
public SomeType2 Prop { get; set; } = null!;VD>Вот собственно стало очевидно, что система нулабельности для этого не приспособлена.
VD>Предлагаю расширить C# блоком инициализации, внутри которого не будет проверяться нулабельность, а все проверки будут осуществляться при выходе из него:
VD>init (var obj1 = new SomeType1()) // не ругается на то, что obj1.Prop1 не заполнен
VD>…А #nullable disable и #nullable restore (здесь) не подходят?
#nullable disable
var obj1 = new SomeType1 { Prop = null, }; // No warning here
var obj2 = new SomeType2 { Prop = obj1, };
obj1.Prop = obj2;
#nullable restore
obj1.Prop = GetNullable(); // CS8601 Possible null reference assignment.
static SomeType2? GetNullable() => null;
file sealed class SomeType1 { public SomeType2 Prop { get; set; } = null!; };
file sealed class SomeType2 { public SomeType1 Prop { get; set; } = null!; };По идее вся засада в том, как объявить подобное свойство, которое должно быть проинициализированно после конструктора / инициализатора?
Я бы попробовал отказаться от null-ов как-то так:
file sealed class SomeType1
{
public SomeType1() { }
private SomeType1(bool uninitialized) {
Debug.Assert(uninitialized);
}
internal static SomeType1 Uninitialized { get; } = new SomeType1(uninitialized: true);
public SomeType2 Prop { get; set; } = SomeType2.Uninitialized;
public void PostInitialization() {
if(Prop == SomeType2.Uninitialized) {
throw new InvalidOperationException();
}//if
}
};
file sealed class SomeType2
{
public SomeType2() { }
private SomeType2(bool uninitialized) {
Debug.Assert(uninitialized);
}
internal static SomeType2 Uninitialized { get; } = new SomeType2(uninitialized: true);
public SomeType1 Prop { get; set; } = SomeType1.Uninitialized;
public void PostInitialization() {
if(Prop == SomeType1.Uninitialized) {
throw new InvalidOperationException();
}//if
}
};