C# equivalent to C "union"?

Is there a C# equivalent to the C union typedef I have a 64 byte array that can either be byte or int (USB data packet). I would like to be able to access these bytes as either type. In C I would declare:

typedef union byte_array
{
struct{byte byte1; byte byte2; byte byte3; byte byte4;};
struct{int int1; int int2;};
};byte_array

 

...and access them by:

byte_array myarray;
mybyte = myarray.byte1;
myint = myarray.int1;

 
How would I accomplish this in C#


Answer this question

C# equivalent to C "union"?

  • DerekM

    Yep that's right.

    Cheers

    David

  • forkart

    David & James - if the data didnt have to 'match' the layout as presented by a C program, say, what would you recommend for storage of these data

  • difg

    James,

    You may want to fix up FieldOffset for the Int2 field in your struct. It should be changed from 1 to 4.

  • ChrisCC

    Good catch, David. I was thinking it was the second int and therefore position 1, but the field numbering is based on the bytes. Serves me right for not dropping it into VS or Snippet Compiler and verifygin it before posting. Thanks!


  • squeakstar

    You can actually do the following:


    using System;
    using System.Runtime.InteropServices;

    [StructLayout(LayoutKind.Explicit)]
    struct byte_array
    {
     [FieldOffset(0)]
     public byte byte1;

     [FieldOffset(1)]
     public byte byte2;

     [FieldOffset(2)]
     public byte byte3;

     [FieldOffset(3)]
     public byte byte4;

     [FieldOffset(0)]
     public short int1;

     [FieldOffset(2)]
     public short int2;
    }


     



    However, you need to be careful as the 'int' datatype in the .NET Framework is actually a 32-bit integer not 16-bit. So 2 bytes actually make up 1 short.



  • TheCatty

    It would honestly depend on a variety of other factors. If I could detect the type of the incoming data, I would create two different structs and let the CLR lay them out optimally based on the underlying platform (x86, IA64, x64, etc.). Then I could select whichever data structure I needed at runtime. I might also consider an abstract base class with common methods and then two concrete classes that contain the data. Yet another option would be a generic type with element type specified as a template parameter. Lots of options and the best option depends on the problem at hand.

  • Phattim

    C# doesn't natively support the C/C++ notion of unions. You can however use the StructLayout(LayoutKind.Explicit) and FieldOffset attributes to create equivalent functionality. I'll assume that you meant a 64-bit data structure, which would contain 8 bytes or 2 ints. If you really did mean a 64-byte data structure, you would need to define a struct with 64 bytes and 16 ints. (Probably better to use a byte[] and a int[].) You can find information here:

    http://winfx.msdn.microsoft.com/library/default.asp url=/library/en-us/dv_csref/html/163ab9b5-46f6-4d78-9025-f7bbba89b2e1.asp

    For instance:

    using System.Runtime.InteropServices;
    [StructLayout(LayoutKind.Explicit)]
    struct ByteArray {
      [FieldOffset(0)]
      public byte Byte1;
      [FieldOffset(1)]
      public byte Byte2;
      [FieldOffset(2)]
      public byte Byte3;
      [FieldOffset(3)]
      public byte Byte4;
      [FieldOffset(4)]
      public byte Byte5;
      [FieldOffset(5)]
      public byte Byte6;
      [FieldOffset(6)]
      public byte Byte7;
      [FieldOffset(7)]
      public byte Byte8;
      [FieldOffset(0)]
      public int Int1;
      [FieldOffset(4)]
      public int Int2;
    }

    One thing to be careful of is the endian-ness of the machine if you plan to run it on non-x86 platforms that may have differing endianness. See http://en.wikipedia.org/wiki/Endianness for an explanation.



  • Cornishboy

    +1, David. We obviously posted our solution at the same time. :)

  • David Leibowitz

    James,

    Great minds think a like. Looks like we posted the same answer at the same time. ;)

  • Jeff Barton

    There is no union in C#. Other options are necessary, such as unsafe code, or a class like this

    public class U {

    short s;

    //==================================================

    public U(short s) {

    this.s = s;

    }

    //==================================================

    public byte AsByte(byte index) {

    const short maskLeft = 0xF0;

    const short maskRight = 0x0F;

    switch (index) { // index: 0..3

    case 0:

    return (byte)((maskLeft & s) >> 4); // shift right 4 bits

    case 1:

    return (byte)(maskRight & s);

    default:

    return 0;

    }

    }

    }



     

    where the access code is written to favor bytes or shorts, whichever values are the most common. sorry about the code format



  • rjhdakota

    Peter, David, James,

    Thanks for the help!

    So, to reference the "int1" above, would I do the following


    myint = byte_array.int1
     


    I will modify the structure for "short" instead of "int" since the other end of the USB link thinks ints are 16 bits...;)

    Thanks again!

  • C# equivalent to C "union"?