2010-01-22 107 views
3

有可能使用結構的大小


Marshal.SizeOf(typeof(mystruct));

是否有可能得到一個結構的一部分的大小(例如我傳遞的功能結構的最後一個字段來獲得結構的大小和它返回以前的字段大小之和)? 據我瞭解有可能使用反射?

+0

爲什麼需要這個?你真的是在編組任何東西,或者只是濫用編組提供一些不應該在C#中使用的東西嗎? – Thorsten79 2010-01-22 11:37:14

+0

我正在從二進制流讀取結構,我只需要一個字節而不是讀取整個結構。 而不是手動計算該字節的偏移量,我想以編程方式執行該操作 – tga 2010-01-22 11:39:57

+1

如果您打算使用結構中的其他字段,我認爲您應該只是反序列化/加載整個二進制流。特別是因爲這是你需要的最後一個領域 - 你會跳過字節找到你需要的字節,只能回頭查看其他字段。 – Codesleuth 2010-01-22 11:53:17

回答

3
[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(); 
    } 
} 

打印: 場B1偏移:0 場B2偏移:3 場I1偏移:7 場I2偏移:12

+0

這就是我正在尋找..但我認爲它不會與[StructLayout(LayoutKind.Explicit)]標記的結構無效[ – tga 2010-01-22 12:39:48

+0

]是的,它不起作用。僅適用於具有此屬性的結構。你無法達到任意結構。這是一個問題嗎?或者你不能改變現有的代碼? – 2010-01-22 12:46:10

1

嗯,我不確定,但我認爲這是不可能的,由於可能的優化和對齊問題。

+0

IIRC。除非使用'StructLayoutAttribute',否則CLR可以重新排列類型的字段以提供更好的佈局。 – Richard 2010-01-22 12:06:44

+0

但我有StructLayout標記的結構 – tga 2010-01-22 12:27:33

2

結構的內存佈局在.NET中不可發現。 JIT編譯器利用這一點,它重新排序結構的字段以獲得更高效的佈局。這對任何試圖以繞過正常編組機制的方式來使用結構都會造成嚴重破壞。是的,Marshal.SiseOf()爲結構產生一個大小。但是這個大小隻有在使用Marshal.StructureToPtr()後纔有效。

直接回答你的問題:不,你無法發現大小,甚至沒有反思。通過設計。