Pull to refresh

Comments 26

NR типы носят скорее рекомендательный характер, ведь нам никто строго не запрещает передать null в NNR тип

На мой взгляд, вывод неправильный.
При должном старании все гарантии компилятора и рантайма носят рекомендательный характер — при помощи unsafe и указателей можно поломать что угодно. В том же духе можно сказать "GC — отличная идея, но мне не запрещают вызвать Marshal.AllocHGlobal и память утекает".


Проблема в другом — даже при включенном warnings as errors и без единого использования ! нет 100% защиты от NRE. Помимо этого, фреймворк не весь проаннотирован, что уж говорить о сторонних библиотеках. Так что по-прежнему приходится держать nullability в уме. Хотя даже в таком виде фича, безусловно, очень полезная — довелось внедрить её на свежем небольшом проекте. В 95% случаев можно полагаться на гарантии и не ломать голову на ревью, нужны ли проверки на null, или нет.

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

Хочу задать вопрос. Вы говорите, что в 95% случаев можно полагаться на гарантии. При этом понятно же это стало уже постфактум. То есть пришлось посмотреть все 100% и уже после понять, что большая часть была правильна. Выходит, что фича приятная, но не более того. Или как Вы понимаете, что в 5% случаев плохие?
Или как Вы понимаете, что в 5% случаев плохие?

Просто запомнил, что в некоторых случаях надо смотреть внимательно (FirstOrDefault и ко, вызовы сторонних библиотек). А в других случаях можно не напрягать мозг — если скомпилилось, то будет работать (работа с вложенными DTO, проверки аргументов в конструкторах и методах).


фича приятная, но не более того

Ну вот опять, мне такие высказывания не очень понятны. Про любую фичу так можно сказать, а звучит не очень. Я бы сформулировал так: "фича предотвращает основную часть NRE ошибок, но есть исключения, о них полезно знать".

Помимо этого, фреймворк не весь проаннотирован, что уж говорить о сторонних библиотеках.

в .NET 5.0 аннотировали почти 90% BCL и будут добавлять аннотации по мере развития языка

Спасибо за уточнение, это я и имел ввиду — даже в грядущей новой версии .NET не 100% покрытие аннотациями в стандартной библиотеке.

Еще задолго до C#8 я перестал использвоать нулы в своем коде и, как результат, практически никогда не встречал NRE, кроме 100500 случаев интеграции с кодом других людей :(. Основная же проблема в том, что раньше у нас был только NotNull от JetBrains.
А теперь появилась возможность явно указать, может быть в коде нулл или нет. Но если человек «явно врет» в своем коде, передавая null под видом not null, это не проблема языка, а проблема программиста-врунишки.

Проблема языка в том, что он в принципе позволяет врать.

public static string RetNull() => null;

А разве всякие Resharper'ы/Rider'ы не выдадут тут ошибку, что возвращаемое значение не может быть null?

Разумеется, я имел ввиду случай, когда он включен.

Если я правильно понял, то в статье имелось ввиду, что он выключен. Но возможно я и не прав…

Это полумеры, лучше в корень репы в Directory.Build.props:


<Project>
    <PropertyGroup>
        <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
        <Nullable>enable</Nullable>
    </PropertyGroup>
</Project>

У этого есть небольшой эффект.
Все предупреждения анализаторов также становятся ошибками.
В принципе это хорошо, но некоторых разработчиков в команде раздражает :)

Ну такое. При дебаге могут появляться, например, неиспользуемые переменные или недостежимый код. В итоге отладка превращается в борьбу с компилятором.
Это хорошо только в новых проектах.

Если работа идёт над legacy, который только только перешагнул на C# 8, такое включение NRT будет вызывать боль и остановит разработку на какое-то время, по понятным причинам.
По опыту могу сказать, что это не такая сложная задача.
Я переводил проект C# на NRT и TypeScript на аналогичный функционал.
Да, может занять пару дней, зато потом становится проще ориентироваться в коде.
А API nuget-пакетов у Вас проаннотированы?

UPD:
По опыту могу сказать, что это не такая сложная задача.

Я думаю, что это в большей степени зависит от размера проекта и его документированности.
С зависимостями бывают проблемы, но не такие серьёзные как может показаться.
Обычно если метод не имеет в названии Try или ещё что-нибудь, то null возвращаться не будет.
У ReSharper-а также есть некоторые дополнительные аннотации.

Если всё к тому, что 100% защиты нет, то это так.
Можно у каждого метода проверять результат на null, но смысла в этом будет не так много.

В статье в самом начале задаётся вопрос про Nullable Reference, а потом на частном примере особенностей реализации в C# делается вывод, что вся идея не ок.
Имхо, так некорректно. Есть ещё много языков с чётким разделением на ссылки(указатели), которые могут и не могут содержать null. Да даже с++, в котором указатели nullable, а ссылки — нет. Не говоря уж про kotlin, scala 3 опциями компилятора или rust.
Сама идея — великолепная и позволяет избежать части багов.

Статья находится в блоге C#, причём тут kotlin, scala и rust?

Данная статья относится только к C#. Если я это не смог донести, то прошу меня простить.

То что сама идея хорошая я и не спорил:
Сама задумка добавить Nullable Reference (далее — NR) типы мне кажется интересной, так как проблема, связанная с разыменованием нулевых ссылок, актуальна и по сей день.

не совсем понимаю как избавиться от nullable types и new на уровне компилятора если в самой логике работы различных подсистем что угодно может вернуть null, от базы данных до результатов поиска, от вычислений до обращения к различным API. как применять это на практике? изолировать nullable-код блоками от не-nullable? или для каждого класса отдельно делать проверки и сопрягать их отдельными композиционным слоем?

попытка избавить нас от лишних проверок на null, – это отличная идея


«Ваш софт — говно!» (ц) Иван Ванко

1. Я на 99.9% уверен, что эта идея пришла как жалкая попытка защититься от индусячего аутсорсного говнокода. Жлоб, который экономит на профессионалах, вынужден тратить В ТРИ раза больше усилий, носясь вокруг дилетантских портянок страны танцоров. Это и моя личная практика тоже — то, что я мог сделать за час, было отдано «дешёвым индусам», после чего я потратил ещё 3 часа на аудит и жонглирование емэйлами, пока результат не стал приемлемым.

2. Залезание в язык только для того, чтобы компенсировать безалаберный код — тухлая затея. Особенно реализованная как у макрософака — глобально и через анус. Тонны легаси кода просто в принципе не подходят под использование в «новом, ненулёвом мире» — ты как и прежде вынужден проверять null'ы. Здесь «легаси» — не какое-то устаревшее говно, а современные библиотеки, которые просто немыслимо велики для того, чтобы вкорячить туда «ненулевой режим» и перелопачивать десятки тысяч строк кода. Другими словами, даже если ты пишешь «новый» код, ты всё равно используешь сторонние библиотеки!

C# «послевосьмёрочной эпохи» напоминает горбатое дитя, которое выросло до 30 лет, а теперь отважные танцоры хирурги пытаются его выпрямить. Вы где раньше-то были?? Сейчас нам ваши скальпели не нужны, поздно. Как поздно вы взялись и за «многоплатформенность». Просто вдумайтесь: взять «виртуальную машину» и умудриться её изуродовать до windows-only — это как надо было постараться?!!!

Нулевые ссылки — это НЕ ПРОБЛЕМА, как не является проблемой невинный оператор goto. Вся проблема — в бесчисленных дилетантах и «гуманитариях», решивших, что «программирование — это просто». Умение писать аккуратный, безопасный код — это признак профессионализма, никакими "!" и "?" его не заменишь. Просто примите это: ПИСАТЬ КОД — ЭТО СЛОЖНО. Этим занимаются «специальные люди» и только их код можно со спокойной душой запускать.

Утечки памяти и висячие указатели — это НЕ ПРОБЛЕМА. Вся проблема — в бесчисленных дилетантах и «гуманитариях». Умение вызывать malloc и free в правильные моменты — это признак профессионализма, никакими Garbage Collector'ами и Borrow Checker'ами его не заменишь.


Зачем программисту возиться с обработкой таких нюансов безопасности, которыми вполне может заниматься компилятор автоматически? Пустая трата времени же.

Sign up to leave a comment.