铸造明确布局的结构

本文关键字:结构 布局 | 更新日期: 2023-09-27 18:22:20

假设我有这个结构,

[StructLayout(LayoutKind.Explicit)]
public struct Chapter4Time
{
    [FieldOffset(0)]
    public UInt16 Unused;
    [FieldOffset(2)]
    public UInt16 TimeHigh;
    [FieldOffset(4)]
    public UInt16 TimeLow;
    [FieldOffset(6)]
    public UInt16 MicroSeconds;
}

以及这种结构。

[StructLayout(LayoutKind.Explicit)]
public struct IEEE_1588Time
{
    [FieldOffset(0)]
    public UInt32 NanoSeconds;
    [FieldOffset(4)]
    public UInt32 Seconds;
}

如何从一种结构转换到另一种结构?

铸造明确布局的结构

这里有两个选项:

没有不安全的代码,但有明确的结构布局

(请注意,尽管就C#编译器而言,这并不不安全,但一些框架可能仍然不允许这样做——请参阅Marc Gravell的评论。)

您可以使用联合类型,它只是另一个具有两个字段的结构,这两个字段都显式设置在同一位置。以下是使用您的结构的完整示例:

using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
public struct Chapter4Time
{
    [FieldOffset(0)]
    public UInt16 Unused;
    [FieldOffset(2)]
    public UInt16 TimeHigh;
    [FieldOffset(4)]
    public UInt16 TimeLow;
    [FieldOffset(6)]
    public UInt16 MicroSeconds;
}
[StructLayout(LayoutKind.Explicit)]
public struct IEEE_1588Time
{
    [FieldOffset(0)]
    public UInt32 NanoSeconds;
    [FieldOffset(4)]
    public UInt32 Seconds;
}
[StructLayout(LayoutKind.Explicit)]
public struct TimeUnion
{
    [FieldOffset(0)]
    public Chapter4Time Chapter4Time;
    [FieldOffset(0)]
    public IEEE_1588Time IEEE_1588Time;
}
class Test
{    
    static void Main()
    {
        var ch4 = new Chapter4Time { TimeLow = 100, MicroSeconds = 50 };
        var union = new TimeUnion { Chapter4Time = ch4 };
        Console.WriteLine(union.IEEE_1588Time.Seconds);
    }
}

不安全代码,投射指针

如果可以使用不安全的代码,则联合类型的替代方法是将类型为Chapter4Time*的指针强制转换为IEEE_1588Time*:

class Test
{    
    unsafe static void Main()
    {
        var ch4 = new Chapter4Time { TimeLow = 100, MicroSeconds = 50 };
        var ieee1588 = *((IEEE_1588Time*) &ch4);
        Console.WriteLine(ieee1588.Seconds);
    }
}

就我个人而言,如果可能的话,我会尽量避免这样做,但如果你真的,真的想这样做,这些可能是最简单的方法。