铸造明确布局的结构

Rob*_*vey 4 c# struct casting type-conversion

假设我有这种结构,

[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;
}
Run Code Online (Sandbox Code Playgroud)

而这个结构.

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

我如何从一个结构转换到另一个结构?

Jon*_*eet 5

这里有两个选择:

没有不安全的代码,但显式结构布局

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

你可以使用一个union类型,它只是另一个带有两个字段的结构,两个字段都明确地设置在同一个位置.这是使用您的结构的完整示例:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

不安全的代码,铸造指针

到是否可以使用不安全的代码联合类型的替代方法是投类型的指针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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 为什么要避免呢?这不是明确布局的全部要点吗?在其他新闻中,我确实有将方法编组到字节数组的方法,所以我当然可以进行两次方法调用并执行相同的操作,但这看起来有点过分. (3认同)
  • @Jon只是一个旁注 - 与"不安全"编译器开关等无关,但是:有些框架完全不允许"不安全"的代码; 他们通常也不允许工会.含义:CLI的某些部分已将联合视为不安全的代码.这真的很有道理. (2认同)