《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类型。

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,如需转载请自行联系原作者

目录
相关文章
|
1月前
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
31 3
|
1月前
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
41 1
|
29天前
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
14 0
|
2月前
|
C#
C# 可空类型(Nullable)
C# 单问号 ? 与 双问号 ??
48 12
|
2月前
|
算法 安全 测试技术
C#——刘铁猛笔记
C#——刘铁猛笔记
48 0
|
4月前
|
存储 C#
揭秘C#.Net编程秘宝:结构体类型Struct,让你的数据结构秒变高效战斗机,编程界的新星就是你!
【8月更文挑战第4天】在C#编程中,结构体(`struct`)是一种整合多种数据类型的复合数据类型。与类不同,结构体是值类型,意味着数据被直接复制而非引用。这使其适合表示小型、固定的数据结构如点坐标。结构体默认私有成员且不可变,除非明确指定。通过`struct`关键字定义,可以包含字段、构造函数及方法。例如,定义一个表示二维点的结构体,并实现计算距离原点的方法。使用时如同普通类型,可通过实例化并调用其成员。设计时推荐保持结构体不可变以避免副作用,并注意装箱拆箱可能导致的性能影响。掌握结构体有助于构建高效的应用程序。
123 7
|
4月前
|
程序员 C#
C# 语言类型全解
C# 语言类型全解
25 0
|
4月前
|
开发框架 .NET 编译器
C# 中的记录(record)类型和类(class)类型对比总结
C# 中的记录(record)类型和类(class)类型对比总结
|
4月前
|
传感器 开发框架 JSON
聊聊 C# dynamic 类型,并分享一个将 dynamic 类型变量转为其它类型的技巧和实例
聊聊 C# dynamic 类型,并分享一个将 dynamic 类型变量转为其它类型的技巧和实例
178 0
|
6月前
|
关系型数据库 C# 数据库
技术笔记:MSCL超级工具类(C#),开发人员必备,开发利器
技术笔记:MSCL超级工具类(C#),开发人员必备,开发利器
55 3