4 ms·
This seems quite a leap from "C# doesn't (yet) have union types" to "structs are horrible in practice". Not all usecases require union types.
by virgilp 6y ago
This seems quite a leap from "C# doesn't (yet) have union types" to "structs are horrible in practice". Not all usecases require union types.
- Ygg2 6y agoStructs are often horrible in practice if you need even a bit of polymorphism. If C# had the ability to define List< struct A | B | C > I would been singing a different tune. You either in for List<IInterface> or List<ABCFieldOffset>
- zigzag312 6y agoThis would be beautiful
- csharptwdec19 6y agoThere's a few challenges with doing something like this. - arrays (which most collections use under the covers) will need to allocate `elements*size_of_struct`. Unless the structs are the same size, you'd have to do some level of thunking/offsetting. - Even if they are the same size, when you're iterating the list, how would the runtime know whether it's `A`, `B`, or `C`? Structs don't have header information that can be used to infer the type, it's only whatever fields you've defined (with padding potentially). Part of 'boxing' is essentially thunking the struct by wrapping a methodtable for the struct into the object [0]. If you need something like polymorphism with structs, your best bet is to make the struct itself quasi-polymorphic (i.e. with enums) and/or start abusing generics in some fashion I haven't yet figured out. [0] - https://mattwarren.org/2017/08/02/A-look-at-the-internals-of-boxing-in-the-CLR/ https://mattwarren.org/2017/08/02/A-look-at-the-internals-of...
- Ygg2 6y ago> Structs don't have header information that can be used to infer the type, it's only whatever fields you've defined (with padding potentially). Sure, so let's make union or "struct enum" and do the same thing Rust does. Add a discriminator byte to the structure and use it to figure out type. > If you need something like polymorphism with structs, your best bet is to make the struct itself quasi-polymorphic (i.e. with enums) and/or start abusing generics in some fashion I haven't yet figured out. Well. I think there is the FieldOffset hack. Basically discriminated unions where programmer plays the role of compiler. [StructLayout(LayoutKind.Explicit)] struct DiscriminatedUnion { // Imagine we have enum like so // enum // { // V1(byte a, byte b) // V2(sbyte a, sbyte b) // } // The "FieldOffset" means that this Integer starts, an offset in bytes. // sizeof(byte) = 1, sizeof(EnumType) = 1 [FieldOffset(0)] public EnumType TypeFlag; [FieldOffset(1)] public byte V1a; [FieldOffset(2)] public byte V1b; [FieldOffset(1)] public sbyte V2a; [FieldOffset(2)] public sbyte V2b; } https://sodocumentation.net/csharp/topic/5626/how-to-use-csharp-structs-to-create-a-union-type---similar-to-c-unions- https://sodocumentation.net/csharp/topic/5626/how-to-use-csh... Problem is, this is fragile. It might break on endianess.
- alkonaut 6y ago> Structs are often horrible in practice if you need even a bit of polymorphism I think that's what he is saying. That it's quite a leap from "structs are horrible in practice" to "structs are horrible if you need polymorphism in conjuction with structs" which is in my experience a pretty rare situation. If you approach structs from Rust or C++ you might expect to be able to form hierarchies of them, but approaching it from Java you are very happy to just be able to create a Point(X, Y) struct. Even the rust type of enum structs with clever overlapping layouts I find pretty rare use for. The common use case is homogeneous data. If I have polymorphism, I'm likely going to incur some pretty expensive virtcalls etc anyway. At that point I just use classes.