C 語言中的 C 風格聯合

聯合型別以多種語言(如 C 語言)使用,以包含可以重疊的幾種不同型別。換句話說,它們可能包含不同的欄位,所有欄位都以相同的記憶體偏移量開始,即使它們可能具有不同的長度和型別。這樣既可以節省記憶體,又可以進行自動轉換。以一個 IP 地址為例。在內部,IP 地址表示為整數,但有時我們想要訪問不同的 Byte 元件,如 Byte1.Byte2.Byte3.Byte4。這適用於任何值型別,無論是 Int32 或 long 等原語,還是你自己定義的其他結構。

我們可以通過使用顯式佈局結構在 C#中實現相同的效果。

using System;
using System.Runtime.InteropServices;

// The struct needs to be annotated as "Explicit Layout"
[StructLayout(LayoutKind.Explicit)]
struct IpAddress
{
    // The "FieldOffset" means that this Integer starts, an offset in bytes.
    // sizeof(int) 4, sizeof(byte) = 1
    [FieldOffset(0)] public int Address;
    [FieldOffset(0)] public byte Byte1;
    [FieldOffset(1)] public byte Byte2;
    [FieldOffset(2)] public byte Byte3;
    [FieldOffset(3)] public byte Byte4;

    public IpAddress(int address) : this()
    {
        // When we init the Int, the Bytes will change too.
        Address = address;
    }

    // Now we can use the explicit layout to access the 
    // bytes separately, without doing any conversion.
    public override string ToString() => $"{Byte1}.{Byte2}.{Byte3}.{Byte4}";
}

以這種方式定義了 Struct,我們可以像在 C 中使用 Union 一樣使用它。例如,讓我們建立一個 IP 地址作為隨機整數,然後通過更改它將地址中的第一個標記修改為'100’從’ABCD’到'100.BCD’:

var ip = new IpAddress(new Random().Next());
Console.WriteLine($"{ip} = {ip.Address}");
ip.Byte1 = 100;
Console.WriteLine($"{ip} = {ip.Address}");

輸出:

75.49.5.32 = 537211211
100.49.5.32 = 537211236

檢視演示