一直以为像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类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
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中每个字段的改变都会影响另一个字段的值。
本文转自wang_yb博客园博客,原文链接:http://www.cnblogs.com/wang_yb/archive/2011/06/20/2084945.html,如需转载请自行联系原作者