《CLR Via C# 第3版》筆記之(五) - C#中的偽Union類型
一直以為像C#這種內存自動回收的語言,開發人員無法操作其在內存的布局。現在才知道,CLR也提供了相應的接口,讓我們可以更細粒度的對代碼進行控制。
主要內容
- C#中控制內存布局的Attribute
- 模擬C#中的Union類型
1. C#中控制內存布局的Attribute
為了控制自己定義的類或結構在內存中的布局,CLR提供了System.Runtime.InteropServices.StructLayoutAtrribute這個Attribute。
這個Attribute的構造器中提供了3種Layout:
1)LayoutKind.Auto : 由CLR自動排列字段
2)LayoutKind.Explicit :讓CLR保持你自己的字段布局
3)LayoutKind.Sequential :利用偏移量在內存中顯示排列字段
如果不指定StructLayoutAtrribute,CLR會選擇它認為最好的布局。
默認情況下,Microsoft C#編譯器對于引用類型選擇LayoutKind.Auto,對值類型選擇LayoutKind.Sequential。
當然,根據自己的需要可以手動修改。
2. 模擬C#中的Union類型
通過指定LayoutKind.Explicit,將結構體中每個字段開始位置的偏移量都指定為0來模擬Union類型。
using System;
using System.Runtime.InteropServices;
class Test
{
static void Main()
{
Union u = new Union();
// 初始化后Union中的值均為0
Console.WriteLine("after initialized: m_a="+u.m_a + " m_b="+u.m_b);
// m_a賦予最大值后,m_b也隨之改變
u.m_a = Byte.MaxValue;
Console.WriteLine("after [u.m_a = Byte.MaxValue]: m_a=" + u.m_a + " m_b=" + u.m_b);
// m_b賦予的值大于m_a上限后,m_a溢出后重新計算為0
// 如果m_b=Byte.MaxValue + 2,依次類推,m_a溢出后重新計算為1
u.m_b = Byte.MaxValue + 1;
Console.WriteLine("after [u.m_b = Byte.MaxValue + 1]: m_a=" + u.m_a + " m_b=" + u.m_b);
Console.ReadKey(true);
}
}
[StructLayout(LayoutKind.Explicit)]
public struct Union
{
[FieldOffset(0)]
public Byte m_a;
[FieldOffset(0)]
public Int32 m_b;
}
如上所示,結構體Union中每個字段的改變都會影響另一個字段的值。

浙公網安備 33010602011771號