runtime: Nullable must be a readonly struct
Nullable<T>
is known to be an immutable struct with sideeffect-free methods.
C# compiler certainly relies on the implied purity for the soundness of null-propagating math as well as in various optimizations.
Basically - while for other structs readonly
is a good thing to have, if possible. I think the spec for Nullable<T>
should demand that Nullable<T>
is formally readonly
.
In particular we consider methods like HasValue
not mutating and therefore callable directly on references to readonly fields (which is currently unverifiable). When verification rules are updated to understand readonly references, we would need to special case Nullable<T>
methods. - Unless the type is readonly
by the spec, then the behavior would be subsumed by the general treatment or readonly
structs.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 1
- Comments: 22 (22 by maintainers)
@danmosemsft, the compiler doesn’t necessarily know about the fields. For example, when writing code against
DateTime
, you’re compiling against theDateTime
from ref assembly, at which point there are no fields. And even if it did, the readonly-ness is part of the contract, so whereas it’s not a breaking change to remove readonly from a field, it would be a breaking change if you removed readonly from a field and the compiler had previously used that knowledge in another compilation unit to treat that type as readonly.Methods that Nullable overrides appears to propagate mutations to inderlying value. I wonder if that is deliberate. I guess that could be to match behavior of fancy boxing, which also exposes underlying to mutations.
I think we should specialcase HasValue, Value, ValueOrDefault as nonmutating in the compiler and tweak proposed verification rules for readonly refs accordingly.
That’s the second part of what I wrote:
If the readonly-ness is implict, then it becomes a breaking change to remove readonly from a field when every other field is also readonly, as someone could have taken a dependency on it even though it wasn’t intended to be a publicly visible fact. This would also wreak havoc on ref assemblies, where every struct could be marked readonly implicitly due to not having any fields.