I'm wondering if C# 7.3's Unmanaged type constraint provides language support for enforcing that a type is blittable. According to Blittable and Non-Blittable types correctly making platform invoke calls requires asserting that the return type is blittable:
Structures that are returned from platform invoke calls must be blittable types. Platform invoke does not support non-blittable structures as return types.
The official documentation doesn't seem to state anywhere that C# enforces that an unmanaged
type is "blittable", however. I'm apprehensive about assuming so because there is evidence that, at one time at least, whether a type is "blittable" could only be determined empirically.
Unmanaged type constraint documentation
The C# 7.3 "Unmanaged type constraint" proposal includes the following:
The unmanaged constraint feature will give language enforcement to the class of types known as "unmanaged types" in the C# language spec. ...
...
Blittable vs. Unmanaged
The F# language has a very similar feature which uses the keyword unmanaged. The blittable name comes from the use in Midori. May want to look to precedence here and use unmanaged instead.
Resolution The language decide to use unmanaged
...
The phrase "unmanaged types" here seems to refer to "unmanaged_type" defined in Unsafe code - Pointer Types of the draft C# 6 specification (I did not find a similar reference in the C# 5 ECMA standard). unmanaged_type is defined as follows:
An unmanaged_type is any type that isn't a reference_type or constructed type, and doesn't contain reference_type or constructed type fields at any level of nesting. In other words, an unmanaged_type is one of the following:
sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, char
, float
, double
, decimal
, or bool
.
- Any enum_type.
- Any pointer_type.
- Any user-defined struct_type that is not a constructed type and contains fields of unmanaged_types only.
I haven't found C# 7.3's unmanaged
type constraint mentioned in the interop marshaling documentation; that documentation seems to predate that feature.
Blittable type documentation
Blittable and Non-blittable Types states that the following are blittable:
System.Byte
, System.SByte
, System.Int16
, System.UInt16
, System.Int32
, System.UInt32
, System.Int64
, System.UInt64
, System.IntPtr
, System.UIntPtr
, System.Single
, System.Double
- One-dimensional arrays of blittable types, such as an array of integers. However, a type that contains a variable array of blittable types is not itself blittable.
- Formatted value types that contain only blittable types (and classes if they are marshaled as formatted types). For more information about formatted value types, see Default marshaling for value types.
Is every unmanaged
type "Blittable"?
At first I thought that the above definitions imply that every unmanaged
type is "blittable". But I haven't found any official documentation that comes right out and states that. The closest I have found is this reply from (as I understand the timeline) before the unmanaged
type constraint feature was implemented:
How is this related to Blittable Types in Interop Marshaling? The same? or similar but bit different?
It's the same.
That seems like evidence in the affirmative, but it's also rather weak evidence upon which to base design decisions. (FWIW, that exchange could also by interpreted as the meaning that all "blittable" types are unmanaged
which seems less likely to be true.)
And then there's the matter of bool
which isn't "blittable" and System.Boolean
which is unmanaged
according to the documentation. That complication is acknowledged but not directly addressed for the interop marshaler in the original proposal.
Why I'm apprehensive about this
I was not an active C# developer while the history of this seems to have unfolded and there are surely clues I've missed. Of the clues I have found, many are in the negative; there seems to have been a time when the implementation of P/Invoke resisted a total intensional definition distinguishing between blittable and non-blittable types. In other words, there were at least some versions of C# where it was non-trivial (or perhaps not possible) to confirm a priori whether the interop marshaler considered a type to be blittable. Or at least it seems that way. For example, Hans Passant wrote in 2015
There is no easy way to find out if a type is blittable, other than it not working correctly or by using the debugger and compare pointer values.
Another clue is that each of the approaches to the answers in The fastest way to check if a type is blittable? (asked in 2012) seem to be empirical. This seems like further evidence in the negative.
I suppose it could be that all unmanaged
types are "blittable" but not all "blittable" types are unmanaged
. But that's just speculation on my part.
question from:
https://stackoverflow.com/questions/65833341/does-c-sharp-enforce-that-an-unmanaged-type-is-blittable