tags:

views:

80

answers:

3
+2  Q: 

Size of structure

It is possible to get size of struct using


Marshal.SizeOf(typeof(mystruct));

Is it possible to get size of a part of a structure(for example I pass to function the last field of a structure and it returns sum of sizes of previous fields)? As I understand is it possible using reflection?

+1  A: 

Well, I'm not sure but I think it's impossible due to possible optimization and alignment issues.

flashnik
IIRC .the CLR can rearrange the fields of a type to give better layout, unless you use `StructLayoutAttribute`.
Richard
But I have my structures marked with StructLayout
TGadfly
+1  A: 

The memory layout of a struct is not discoverable in .NET. The JIT compiler takes advantage of this, it re-orders the fields of a struct to get a more efficient layout. This plays havoc with any attempt to use the struct in a way that bypasses the normal marshaling mechanisms. Yes, Marshal.SiseOf() produces a size for a struct. But that size is only valid after using Marshal.StructureToPtr().

A direct answer to your question: no, you can't discover the size, not even with Reflection. By design.

Hans Passant
+2  A: 
[StructLayout(LayoutKind.Explicit)]
public struct SomeStruct
{
    [FieldOffset(0)]
    public byte b1;
    [FieldOffset(3)]
    public byte b2;
    [FieldOffset(7)]
    public int i1;
    [FieldOffset(12)]
    public int i2;
}

class Program
{
    static FieldOffsetAttribute GetFieldOffset(string fieldName)
    {
        return (FieldOffsetAttribute)typeof(SomeStruct)
            .GetField(fieldName)
            .GetCustomAttributes(typeof(FieldOffsetAttribute), false)[0];
    }

    static void Main(string[] args)
    {
        var someStruct = new SomeStruct { b1 = 1, b2 = 2, i1 = 3, i2 = 4 };

        Console.WriteLine("field b1 offset: {0}", GetFieldOffset("b1").Value);
        Console.WriteLine("field b2 offset: {0}", GetFieldOffset("b2").Value);
        Console.WriteLine("field i1 offset: {0}", GetFieldOffset("i1").Value);
        Console.WriteLine("field i2 offset: {0}", GetFieldOffset("i2").Value);

        Console.ReadLine();
    }
}

Prints: field b1 offset: 0 field b2 offset: 3 field i1 offset: 7 field i2 offset: 12

Sergey Teplyakov
That is what i was looking for.. But i think it will not work with structures that are not marked with [StructLayout(LayoutKind.Explicit)]
TGadfly
Yes, It will not work. Only for structures with this attribute. You can't achieve this for arbitrary structure. Is this a problem? Or you can't change existing code for that?
Sergey Teplyakov