Proposal: Add a relaxed unmanaged constraint that allows nullable types #9099
Unanswered
vmilea
asked this question in
Language Ideas
Replies: 2 comments
-
Discussion was moved from runtime. Thanks to @huoyaoyuan for the initial feedback. |
Beta Was this translation helpful? Give feedback.
0 replies
-
It has come up in a discussion about ref struct. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Motivation
Nullable<T>
where T : unmanaged
is effectively an unmanaged type (being a struct that contains fields of unmanaged types only). Unfortunately, it doesn't satisfy thestruct
/unmanaged
constraints, which causes bloated APIs like:This becomes exponentially worse the more parameters there are:
To avoid an explosion of overloads, the library author may decide to leave
T
unconstrained and instead throw an exception on misuse:This approach detects issues at runtime with zero overhead, but the method signature no longer states the actual requirements and we lose compile time checks.
Since it's too late to change the semantics of the
unmanaged
constraint, why not add a relaxed form that allows the following?Proposal
Define an
unmanaged?
constraint which doesn't implystruct
, so it accepts both unmanagedT
andT?
.Crucially, no CLR changes are needed -- from the perspective of the runtime, the type appears unconstrained.
unmanaged?
can be expressed through attributes on generic parameters and enforced at compiler level (similar to how nullable reference types are checked).Alternative Designs
Register a code analyzer to constrain the parameters:
This approach doesn't need compiler support, and could enforce additional rules like excluding auto layout types. However, processing all references for each annotated method and type may be too expensive with large projects.
Q/A
No. This proposal is for a separate constraint without breaking changes or CLR involvement.
default
value expressions be supported forunmanaged?
types?Yes. Zero initialization is fine for both unamanged
T
andNullable<T>
.unmanaged?
imply thenew()
constraint?While there's no technical reason preventing it, there's no practical benefit either since unmanaged types are typically zero initialized.
struct
?Losing access to minor utilities like
MemoryMarshal.AsBytes<T>(Span<T> span) where T : struct
is largely irrelevant since they can be easily reimplemented unconstrained throughUnsafe
. The essential operations are getting the size ofT
, its alignment, and access to raw bytes, neither of which requires thestruct
constraint.Beta Was this translation helpful? Give feedback.
All reactions