Welcome to SpellCoder Sign in | Join | Help

StructLayout attribute magic

I've been reading for a while in the great CLR via C# second edition book, and here is one of the best things I've seen there,
When you declare a type, the CLR in runtime automatically rearrange the order of your type members for performance, so the access to these members are faster, and also trying to use minimum memory, stuff like making the variables reserves even memory locations for faster access and all these stuff, but you still have control on the CLR to force him follow the sequence you defined, and this helps especially in the interoperability with some C/C++ API's that accepts structs, so you have to stick with the structure layout, and in this case you have to add the StructLayout attribute to your class or struct like this
[StructLayout(LayoutKind.Sequential)]
struct Point
{
int x;
int y;
}
If you are declaring a struct type, the default Layout is Sequential, so you don't need to add the StructLayout.
However, developers add the attribute to struct when they want to mention that this struct is defined for interop with unmanaged stuff.

So where is the fun ?? I already know this
The fun comes here, the LayoutKind actually has three options which are
  1. Auto (which is the default behavior)
  2. Sequential
  3. Explicit
The Explicit is how you can have full control of how the Struct members are stuffed in the main memory,
so you can declare the point like this
[StructLayout(LayoutKind.Explicit)]
struct Point
{
[FieldOffset(0)]
public int x;
[FieldOffset(sizeof(int))]
public int y;
}
So here I defined the struct member X to reserve the bytes starting from offset 0, then the member Y to reserve the bytes starting from offset 4 which is sizeof(int), so the Y will come immediately after X in memory, However you can play with the numbers like making them overlap together and get the garbage data we used to see in C :).
and as long as we are considering overlapping so we can define something like the old C Union data structure, which we can define a data structure that will contain multiple definitions of variables types and the memory that will be reserved is the memory required to store the largest type. for more information about C/C++ Union
So all what you need here, is setting all the variables' offsets declared in the struct to 0, so all of them occupy the same locations in memory, and the memory reserved for them all is the memory for the largest one, and you are only allowed to use ONLY ONE of them, if you tried assigning values to more than one member, this will lead to unexpected behavior and results, so consider this
[StructLayout(LayoutKind.Explicit)]
struct UnionLike
{
[FieldOffset(0)]
public int iValue;
[FieldOffset(0)]
public int lValue;
[FieldOffset(0)]
public double dValue;
}
and this will lead to this memory organization (conceptually)

So the whole UnionLike type reserves 8 bytes in memory which is the size of the largest member (in this case dValue)

This was amazing to me when I first saw it, and I think it worths a try from you.
kick it on DotNetKicks.com
Published Thursday, December 21, 2006 4:05 AM by Mohammed Hossam
Filed Under: ,

Comments

# re: StructLayout attribute magic

Thursday, December 21, 2006 5:36 PM by Adel
nice one, but i have a couple of questions..
as i didn't try this.. when i use LayoutKind.Explicit should i place the code in unsafe/unmanaged block?,also i think i'm getting this in a wrong way, what happend if i crossed a memory fragment thet couldn't hold my seconed peace of memory allocation?

# re: StructLayout attribute magic

Thursday, December 21, 2006 8:46 PM by Mohammed Hossam
First
This doesn't need any Unsafe blocks or anything, this is completely managed and supported by the CLR itself.
Second
I don't know if I got you right, so as far as I could understand from your question, in the Union example you can use ONLY ONE member per structure instance, and this is the idea of Unions in the first place, you faced a situation when you may use a variable of (n) different types, so instead of declaring (n) variables and just use one of them, and waste the other (n-1) variables, Unions reserves enough memory to hold the biggest one of the variables so it makes a union of the sizes

# re: StructLayout attribute magic

Friday, December 22, 2006 7:06 AM by Adel
Now i understand, so we can say this is best practice for memory allocation but i guess the var keyword in the v.next will solve this if i'm right so i'm totally understant what are you getting to.

# re: StructLayout attribute magic

Friday, December 22, 2006 9:09 AM by Mohammed Hossam
the var keyword will help, but still, the var keyword will help you when you assign the value directly in the same line of declaration, because the compiler has to infer the type, but here the compiler doesn't need this, because you already told him all the possible types, so the compiler will reserve the memory that is sufficient to save any one of them.

# re: StructLayout attribute magic

Friday, December 22, 2006 10:12 AM by Adel
many thanks indeed for the responses.

# re: StructLayout attribute magic

Monday, January 01, 2007 6:32 PM by Alexey
So what is returned by

Evil(UnionLike badThing)
{
   badThing.dValue = 1.5;
   return badThing.iValue;
}
?

Let's say someone passes a UnionLike value to you; how do you find out if it contains dValue, lValue, or iValue?

# re: StructLayout attribute magic

Monday, January 01, 2007 8:56 PM by Mohammed Hossam
in your example you're not returning a UnionLike type but you are returning an integer type
also, Unions are used most of time as an internal data structure and they are not supposed to be passed as parameter to a public function.
because you can't tell which type is used inside, unless you are the one who used it in the first place.

# re: StructLayout attribute magic

Thursday, September 06, 2007 10:09 AM by ps3 gamer
helpful for C# .NET, was looking for VB
StructLayout for some games code.
Anonymous comments are disabled