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 и будут добавлять аннотации по мере развития языка
А теперь появилась возможность явно указать, может быть в коде нулл или нет. Но если человек «явно врет» в своем коде, передавая null под видом not null, это не проблема языка, а проблема программиста-врунишки.
public static string RetNull() => null;
А разве всякие Resharper'ы/Rider'ы не выдадут тут ошибку, что возвращаемое значение не может быть null?
Тот, кто не переводит NR предупреждения в разряд ошибок, ССЗБ.
https://gist.github.com/cezarypiatek/f56c671c6f634aab285a88095488c1de
Это полумеры, лучше в корень репы в Directory.Build.props
:
<Project>
<PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
У этого есть небольшой эффект.
Все предупреждения анализаторов также становятся ошибками.
В принципе это хорошо, но некоторых разработчиков в команде раздражает :)
Если работа идёт над legacy, который только только перешагнул на C# 8, такое включение NRT будет вызывать боль и остановит разработку на какое-то время, по понятным причинам.
Я переводил проект C# на NRT и TypeScript на аналогичный функционал.
Да, может занять пару дней, зато потом становится проще ориентироваться в коде.
UPD:
По опыту могу сказать, что это не такая сложная задача.
Я думаю, что это в большей степени зависит от размера проекта и его документированности.
Обычно если метод не имеет в названии Try или ещё что-нибудь, то null возвращаться не будет.
У ReSharper-а также есть некоторые дополнительные аннотации.
Если всё к тому, что 100% защиты нет, то это так.
Можно у каждого метода проверять результат на null, но смысла в этом будет не так много.
В статье в самом начале задаётся вопрос про Nullable Reference, а потом на частном примере особенностей реализации в C# делается вывод, что вся идея не ок.
Имхо, так некорректно. Есть ещё много языков с чётким разделением на ссылки(указатели), которые могут и не могут содержать null. Да даже с++, в котором указатели nullable, а ссылки — нет. Не говоря уж про kotlin, scala 3 опциями компилятора или rust.
Сама идея — великолепная и позволяет избежать части багов.
Статья находится в блоге C#, причём тут kotlin, scala и rust?
То что сама идея хорошая я и не спорил:
Сама задумка добавить Nullable Reference (далее — NR) типы мне кажется интересной, так как проблема, связанная с разыменованием нулевых ссылок, актуальна и по сей день.
не совсем понимаю как избавиться от nullable types и new на уровне компилятора если в самой логике работы различных подсистем что угодно может вернуть null, от базы данных до результатов поиска, от вычислений до обращения к различным API. как применять это на практике? изолировать nullable-код блоками от не-nullable? или для каждого класса отдельно делать проверки и сопрягать их отдельными композиционным слоем?
попытка избавить нас от лишних проверок на null, – это отличная идея
«Ваш софт — говно!» (ц) Иван Ванко
1. Я на 99.9% уверен, что эта идея пришла как жалкая попытка защититься от индусячего аутсорсного говнокода. Жлоб, который экономит на профессионалах, вынужден тратить В ТРИ раза больше усилий, носясь вокруг дилетантских портянок страны танцоров. Это и моя личная практика тоже — то, что я мог сделать за час, было отдано «дешёвым индусам», после чего я потратил ещё 3 часа на аудит и жонглирование емэйлами, пока результат не стал приемлемым.
2. Залезание в язык только для того, чтобы компенсировать безалаберный код — тухлая затея. Особенно реализованная как у макрософака — глобально и через анус. Тонны легаси кода просто в принципе не подходят под использование в «новом, ненулёвом мире» — ты как и прежде вынужден проверять null'ы. Здесь «легаси» — не какое-то устаревшее говно, а современные библиотеки, которые просто немыслимо велики для того, чтобы вкорячить туда «ненулевой режим» и перелопачивать десятки тысяч строк кода. Другими словами, даже если ты пишешь «новый» код, ты всё равно используешь сторонние библиотеки!
C# «послевосьмёрочной эпохи» напоминает горбатое дитя, которое выросло до 30 лет, а теперь отважные
Нулевые ссылки — это НЕ ПРОБЛЕМА, как не является проблемой невинный оператор goto. Вся проблема — в бесчисленных дилетантах и «гуманитариях», решивших, что «программирование — это просто». Умение писать аккуратный, безопасный код — это признак профессионализма, никакими "!" и "?" его не заменишь. Просто примите это: ПИСАТЬ КОД — ЭТО СЛОЖНО. Этим занимаются «специальные люди» и только их код можно со спокойной душой запускать.
Утечки памяти и висячие указатели — это НЕ ПРОБЛЕМА. Вся проблема — в бесчисленных дилетантах и «гуманитариях». Умение вызывать malloc и free в правильные моменты — это признак профессионализма, никакими Garbage Collector'ами и Borrow Checker'ами его не заменишь.
Зачем программисту возиться с обработкой таких нюансов безопасности, которыми вполне может заниматься компилятор автоматически? Пустая трата времени же.
Nullable Reference не защищают, и вот доказательства