Как уже говорил Джон, правильность констант не так проста, как может показаться. C ++ делает это одним способом. D делает это другим (возможно, более правильным / полезным) способом. C # заигрывает с этим, но не делает ничего более дерзкого, как вы обнаружили (и, вероятно, никогда не получится так, как Джон снова прикрыл).
Тем не менее, я считаю, что многие из "теоретических причин" Джона решены в модели Д.
В D (2.0) const работает во многом как C ++, за исключением того, что он полностью транзитивен (поэтому const, примененный к указателю, будет применяться к указанному объекту, любым элементам этого объекта, любым указателям, которые этот объект имел, объектам, которые они указывает на и т. д.) - но очевидно, что это только применяется из переменной, которую вы объявили const (поэтому, если у вас уже есть неконстантный объект, и вы берете на него указатель const, переменная const все еще может изменять состояние).
D вводит другое ключевое слово - инвариант - которое применяется к самому объекту. Это означает, что ничто не может изменить состояние после инициализации.
Прелесть этой схемы в том, что метод const может принимать как const, так и инвариантные объекты. Поскольку инвариантные объекты - это хлеб функциональности, и метод const можно пометить как «чистый» в функциональном смысле, даже если он может использоваться с изменяемыми объектами.
Возвращаясь на правильный путь - я думаю, что это тот случай, когда мы только сейчас (вторая половина непослушных) понимаем, как лучше использовать const (и инвариант). Первоначально .Net был определен, когда все было более туманным, поэтому не слишком много - и теперь уже слишком поздно для модернизации.
Хотелось бы, чтобы порт D работал на .Net VM, хотя: -)