В C++ для определения локальной константы времени выполнения можно написать так:
const auto c = f();
Далее, все попытки изменить c будут приводить к ошибке компиляции.
В C# такой возможности нет. Можно использовать readonly член подобным образом, но не локальную константу.
Почему существует такое ограничение (в чём причина отсутствия локальных констант а-ля C++) и какое каноническое решение имеется для обеспечения локальной константности времени выполнения на C#? Неужели для этого надо создавать отдельный read-only интерфейс?
Ответ
Стоит отметить, что по локальным readonly-переменным есть официальный proposal. Фича опоздала к C# 7, но у нее все шансы войти в C# 8.
Со стороны CLR для реализации нет никаких ограничений - readonly locals, как и все фичи C# со времен .NET 4.0 - это compile-time фичи - т.к. версия рантайма с тех пор не поменялась.
По сути, proposal сводится к нескольким пунктам:
возможности помечать параметры как readonly
возможности помечать переменные как readonly
шорткату let - эквиваленту readonly var
Локальные readonly, как и неизменяемые foreach iteration variable - это, прежде всего, защита от дурака/ошибки копипасты. И уже потом - способ указать компилятору на возможную оптимизацию замыканий.
На мой взгляд, сама по себе возможность вручную приписывать readonly к локальным переменным только ради в качестве защиты от потенциальной ошибки - неудобна для реального использования. Достаточно вспомнить о final в Java. Поэтому без шортката let фича будет достаточно бесполезной - ее будут использовать фанаты "безопасного кода" - те, кто сейчас принципиально не использует var и явно вписывают типы во всех упоминаниях генерика.
Остальные пойдут по пути наименьшего сопротивления - гораздо дешевле и проще исправить одну ошибку раз в месяц, чем приписывать readonly к каждой переменной. Ну и опять же, тесты, при правильном применении, решают проблему ошибок копипасты.
Более надежный способ защиты реализован, например, в F#, где локальные значения по умолчанию неизменяемы, а = вне объявления значения вообще не работает как оператор присвоения.
let x = 1
x = 2 // This expression should have type 'unit', but has type 'bool'
Для изменения значения разработчику придется сделать дополнительные телодвижения, как в строчке где переменная объявлена, так и в строчке, где переменная изменяется.
let mutable x = 1
x <- 2
Сам язык подталкивает его к тому, чтобы объявить еще одно значение, а не менять существующее. Одна из трех добродетелей программиста - лень - уберегает его от ошибки.
А просто так дописывать readonly к переменным, "как бы чего не вышло" - никто, кроме особых фанатов, не будет - из соображений той же лени.
Комментариев нет:
Отправить комментарий