2010-01-22 101 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()后才有效。

直接回答你的问题:不,你无法发现大小,甚至没有反思。通过设计。