.NET Multi-platform App UI – фреймворк, который пишут профессионалы. Тем не менее, код некоторых его функций выглядит так, будто разработчики забыли о последствиях разыменования нулевых ссылок.

Небольшая вводная
Не берусь судить об общем качестве проекта MAUI, но у меня есть сильные подозрения, что проекту предстоит пройти долгий путь фиксов по фидбеку от пользователей про неожиданные NullReferenceException.
Код создаёт впечатление, что авторы очень торопятся при его написании. Из-за этого во многих местах без проверок разыменовываются ссылки, которые, по мнению самих же разработчик��в, могут быть нулевыми. Чтобы было понятнее, давайте взглянем на отдельные фрагменты из исходников MAUI 6.0.424.
Почему так?
Именно этот вопрос я задавал себе, когда глядел на фрагменты, представленные далее. Либо я чего-то не понял, либо разработчики MAUI пишут очень странный код.
К примеру, взгляните на фрагмент из функции AttachEvents класса AdaptiveTrigger:
void AttachEvents()
{
....
_visualElement = VisualState?.VisualStateGroup?.VisualElement;
if (_visualElement is not null)
_visualElement.PropertyChanged += OnVisualElementPropertyChanged;
_window = _visualElement.Window; // <=
....
}
Тут выходит какая-то ерунда. Судя по двум "?." и проверке "is not null", в поле _visualElement может быть null. И буквально тут же мы видим обращение к свойству Window, но уже без проверки. Видимо, проглядели.
Ладно, идём дальше. Взгляните на фрагмент из класса FormattedString:
void OnCollectionChanged(....)
{
....
foreach (object item in e.OldItems)
{
var bo = item as Span;
bo.Parent = null; // <=
if (bo != null)
{
....
}
....
}
Опять соседние строчки. Сначала разыменовали bo, а затем вдруг решили проверить его на null. Я не знаю, падает ли этот код в каких-то случаях, но выглядит это всё странно.
А вот кусочек из класса ListView:
protected override void SetupContent(Cell content, int index)
{
....
if (content != null)
_logicalChildren.Add(content);
content.Parent = this;
VisualDiagnostics.OnChildAdded(this, content);
}
Тут снова какая-то ерунда. Почему в коллекцию элемент добавляется с проверкой, а к свойству мы обращаемся уже без неё?
Ещё одну "полезную" проверку на null я нашёл в конструкторе класса ShellChromeGallery:
AppShell AppShell => Application.Current.MainPage as AppShell;
public ShellChromeGallery()
{
....
if (AppShell != null)
{
flyoutBehavior.SelectedIndex = ....;
flyoutHeaderBehavior.SelectedIndex = ....;
}
else
{
flyoutBehavior.SelectedIndex = 1;
flyoutHeaderBehavior.SelectedIndex = 0;
}
AppShell.FlyoutBackdrop = SolidColorBrush.Pink; // <=
}
Ну тут опять всё круто: проверяем на null, выставляем при необходимости какие-то дефолтные значения, а потом сразу же падаем.
Учитывая то, как часто попадаются странные фрагменты, я даже начал думать, что проверка на равенство null – совсем не то, чем кажется. Ну, к примеру, в том же Unity оператор "==" перегружен и проверка на равенство null там работает по-особому. Однако в MAUI ничего такого я не увидел.
А почему же всё-таки так?
MAUI пишут профессионалы, но проект очень уж большой и сложный. Люди ошибаются, и это нормально. Странно другое: такие проблемы вполне могут отлавливать различные автоматизированные инструменты. К примеру, как несложно догадаться, я нашёл показанные фрагменты с помощью C# анализатора PVS-Studio. На мой взгляд, подобные инструменты сильно бы упростили жизнь разработчикам MAUI. А в целом желаю им успехов с развитием проекта.
Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Nikita Lipilin. Do you plan to take on .NET MAUI? Get ready for an adventure with NullReferenceException.