Como Jon ya está cubierto (por supuesto) const correctness no es tan simple como podría parecer. C++ lo hace de una manera. D lo hace de otra manera (posiblemente más correcta/útil). C# coquetea con él, pero no hace nada más atrevido, como habrás descubierto (y probablemente nunca bien, ya que Jon volvió a cubrirse).
Dicho esto, creo que muchas de las "razones teóricas" de Jon se resuelven en el modelo de D's.
En D (2.0), const funciona de forma muy parecida a C++, excepto que es totalmente transitiva (por lo que se aplicaría a un puntero al objeto apuntado, cualquier miembro de ese objeto, cualquier puntero que ese objeto tuviera, objetos apuntaban a etc.), pero es explícito que este solo aplica a partir de la variable que ha declarado const (por lo que si ya tiene un objeto no const y toma un puntero const a él, la variable no const puede todavía mutar el estado).
D introduce otra palabra clave - invariante - que se aplica al objeto en sí. Esto significa que nada puede cambiar el estado una vez inicializado.
La belleza de esta disposición es que un método const puede aceptar tanto objetos const como invariantes. Dado que los objetos invariables son el pan y la mantequilla del mundo funcional, y el método const se puede marcar como "puro" en el sentido funcional, incluso aunque se pueda usar con objetos mutables.
Volviendo a la pista: creo que es el caso de que solo ahora (la segunda mitad de las travesuras) comprendamos la mejor forma de usar const (e invariante). .Net se definió originalmente cuando las cosas eran más confusas, por lo que no se comprometió demasiado, y ahora es demasiado tarde para actualizar.
Me encanta ver a un puerto de D corrida contra el .Net VM, aunque :-)
Gracias Jon. Eso es iluminador. –