-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Background and motivation
I apologise if this has already appeared, I don't see an API Proposal for it explicitly (with union in the title)
When dealing with interop with C/C++, and sometimes when porting, there are times when it would be handy to have a union.
API Proposal
union {
[type1] [nameA];
[type2] [nameB];
[type3] [nameC];
}API Usage
[StructLayout(LayoutKind.Sequential)]
struct MyStruct {
public int* thingiesHandle; // unrelated
public int thingiesCount; // unrelated
internal union {
int whyAreTheseInTheSameMemory;
float nobodyKnows;
Vector2OfShort itsAMystery;
fixed byte isThisAStretchTooFar[4];
}
}Alternative Designs
Behind the scenes it would create an explicitly laid out struct the size of its largest member that would behave like a tuple with access to the fields like Unsafe.As or *(T*)ptr. So in that sense perhaps there are alternatives like Tuple<T1,T2>(val1,val2) vs (val1,val2) or Nullable<T> vs T? maybe something like Union<T1,T2,T3> though that wouldn't work at all with fixed buffers.
The other need would be to be able to inject names, which would probably blow a hole in that:
unsafe struct Union<T1, T2> where T1: unmanaged where T2: unmanaged
{
private void* _ptr;
public T1 AsT1 => *(T1*)_ptr;
public T2 AsT2 => *(T2*)_ptr;
}
I'd just want to refer to the aliases by which the same memory goes, rather than myStruct.MyUnion.AsT1 (for example)
Risks
The only fly in the ointment that I can think of is lack of clarity in the IL. You'd be creating a field in the owning struct that has a size, and then just load it as whatever type is being requested just like an unsafe cast. BUT dotnet already produces things with weird names for anonymous types, lambdas, and so forth, and very few people try to understand the code by reading the IL. The performance impact is zero.