千家信息网

C#可空类型原理是什么

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章主要介绍"C#可空类型原理是什么",在日常操作中,相信很多人在C#可空类型原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"C#可空类型原理是什么"的疑惑
千家信息网最后更新 2026年11月01日C#可空类型原理是什么

这篇文章主要介绍"C#可空类型原理是什么",在日常操作中,相信很多人在C#可空类型原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"C#可空类型原理是什么"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

为了方便演示,我就定义一个int?类型,接收非null和null两种情况。


static void Main(string[] args)
{
int? num1 = 10;
int? num2 = null;

Console.WriteLine("执行结束啦!");
Console.ReadLine();
}

1. 挖IL代码

挖IL代码简单,用ILSPY小工具就可以了,编译后生成的IL代码如下:


.method private hidebysig static
void Main (
string[] args
) cil managed
{
// Method begins at RVA 0x2048
// Code size 36 (0x24)
.maxstack 2
.entrypoint
.locals init (
[0] valuetype [mscorlib]System.Nullable`1 num1,
[1] valuetype [mscorlib]System.Nullable`1 num2
)

IL_0000: nop
IL_0001: ldloca.s 0
IL_0003: ldc.i4.s 10
IL_0005: call instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0)
IL_000a: ldloca.s 1
IL_000c: initobj valuetype [mscorlib]System.Nullable`1
IL_0012: ldstr "执行结束啦!"
IL_0017: call void [mscorlib]System.Console::WriteLine(string)
IL_001c: nop
IL_001d: call string [mscorlib]System.Console::ReadLine()
IL_0022: pop
IL_0023: ret
} // end of method Program::Main

这IL代码还是非常易懂的,比汇编简单多啦(┬_┬),可以看到int ? 就是 System.Nullable ,然后从valuetype 标记可以看到这玩意是个值类型,所以把上面的代码回转成C#代码就是下面这样。


{
static void Main(string[] args)
{
//int? num1 = 10;
//int? num2 = null;

Nullable num3 = new Nullable(10);
Nullable num4 = new Nullable();

Console.WriteLine("执行结束啦!");
Console.ReadLine();
}

很简单吧,那怎么输出num3和num4呢? 直接Console.WriteLine就好了。

这里你肯定有一个疑问,为什么num3输出10,而num4什么都没输出呢? 哈哈,这是因为Nullable的ToString()被重写了,再来看下ToString被重写成啥样了,代码如下:

public struct Nullable where T : struct
{
private bool hasValue;

internal T value;

[NonVersionable]
[__DynamicallyInvokable]
public Nullable(T value)
{
this.value = value;
hasValue = true;
}

[__DynamicallyInvokable]
public override string ToString()
{
if (!hasValue)
{
return "";
}
return value.ToString();
}
}

可以看到ToString方法里要么返回空字符串要么返回你在构造函数中塞入的value,这这么简单,IL代码挖到这里就可以了。

2. 挖机器代码

要看num1和num2的机器代码,其实也就是看 Nullable 的内存布局方式,这里我使用windbg,还是使用 !clrstack -l 查看线程栈。


int? num1 = 10;
int? num2 =null;

0:007> ~0s
ntdll!ZwReadFile+0x14:
00007ffc`ec11aa64 c3 ret
0:000> !clrstack -l
OS Thread Id: 0x5364 (0)
Child SP IP Call Site
ConsoleApp4.Program.Main(System.String[]) [C:\dream\Csharp\ConsoleApp1\ConsoleApp4\Program.cs @ 21]
LOCALS:
0x00000018a9dfeaf8 = 0x0000000a00000001
0x00000018a9dfeaf0 = 0x0000000000000000

00000018a9dfed08 00007ffcd5b66c93 [GCFrame: 00000018a9dfed08]

从LOCALS中可以看到,num1和num2的线程栈上存放的内容分别是0x0000000a00000001和 0x0000000000000000, 不过这值也挺奇怪的,一个是1一个是0。。。我们用 dd 命令把地址转储出来。


0:000> dd 0x00000018a9dfeaf8
00000018`a9dfeaf8 00000001 0000000a a9dfec08 00000018
0:000> dd 0x00000018a9dfeaf0
00000018`a9dfeaf0 00000000 00000000 00000001 0000000a

在num1的内存区域中有一个十六进制值 0000000a ,这就是十进制的10,那前面的 00000001 是什么东西呢? 大家不要忘啦, int?是语法糖, 你现在看的是 Nullable 哈。。。

看清楚啦,这个结构体里面有两个值类型字段,自然 00000001 就是 hasValue=true啦。 num2也就好理解了,两个默认值也就是两个0了。00000000 00000000。

三:有意外发现

1. int? 比 int 要占用更多的内存

如果你的内存数据量特别大的话,你就要当心了,int? 比 int 在x64上要多占4个字节,也就是多一倍,无论线程栈还是托管堆。

2. 为什么bool要占用 4字节空间?

<1> 线程栈上的演示

肯定有人比较疑惑,bool在C#中不就是一个字节嘛? 你怎么说是4个字节呢? 你要是问我,我只能说从windbg上看就是这样的,x64系统的线程栈上就是以4个字节为一个单位,你不信的话,我就在代码中定义不同字段的 值类型,你看看在线程栈上的分布不就好啦,以事实说话。

           byte b1 = byte.MaxValue;
byte b2 = byte.MaxValue;
short b3 = short.MaxValue;
short b4 = short.MaxValue;
int b5 = int.MaxValue;
int b6 = int.MaxValue;

0:000> !clrstack -l
OS Thread Id: 0xa98 (0)
ConsoleApp4.Program.Main(System.String[]) [C:\dream\Csharp\ConsoleApp1\ConsoleApp4\Program.cs @ 25]
LOCALS:
0x000000a8395fedbc = 0x00000000000000ff
0x000000a8395fedb8 = 0x00000000000000ff
0x000000a8395fedb4 = 0x0000000000007fff
0x000000a8395fedb0 = 0x0000000000007fff
0x000000a8395fedac = 0x000000007fffffff
0x000000a8395feda8 = 0x000000007fffffff

然后把最小的地址0x000000a8395feda8 转储出来。


0:000> dd 0x000000a8395feda8
000000a8`395feda8 7fffffff 7fffffff 00007fff 00007fff
000000a8`395fedb8 000000ff 000000ff 395feec8 000000a8
000000a8`395fedc8 395fefc8 000000a8 395fee00 000000a8
000000a8`395fedd8 d5b66c93 00007ffc 98e72d30 000001ee
000000a8`395fede8 76504140 00007ffc 00000000 00000000
000000a8`395fedf8 00000000 00007ffc 395feef0 000000a8
000000a8`395fee08 971d0b20 000001ee 00000000 00000000
000000a8`395fee18 d5b66b79 00007ffc 00000000 00000000

对比一下可以看到上面的 7fffffff, 00007fff,000000ff就是相应的int,short,byte的MaxValue, 都是占用4个字节的空间,没问题吧。

<2> 托管堆演示


var arr1 = new int[] { 10 };
var arr2 = new int?[] { 14 };

0:000> !clrstack -l
OS Thread Id: 0x23f8 (0)
000000859a1fec60 00007ffc76630967 ConsoleApp4.Program.Main(System.String[]) [C:\dream\Csharp\ConsoleApp1\ConsoleApp4\Program.cs @ 32]
LOCALS:
0x000000859a1feca0 = 0x000002773cb32d70
0x000000859a1fec98 = 0x000002773cb32d90

000000859a1feeb8 00007ffcd5b66c93 [GCFrame: 000000859a1feeb8]
0:000> !do 0x000002773cb32d70
Name: System.Int32[]
MethodTable: 00007ffcd2d58538
EEClass: 00007ffcd2ec5918
Size: 28(0x1c) bytes
Array: Rank 1, Number of elements 1, Type Int32 (Print Array)
Fields:
None
0:000> !do 0x000002773cb32d90
Name: System.Nullable`1[[System.Int32, mscorlib]][]
MethodTable: 00007ffcd3fb2058
EEClass: 00007ffcd30221a0
Size: 32(0x20) bytes
Array: Rank 1, Number of elements 1, Type VALUETYPE (Print Array)
Fields:
None

0:000> !objsize 0x000002773cb32d70
sizeof(000002773cb32d70) = 32 (0x20) bytes (System.Int32[])
0:000> !objsize 0x000002773cb32d90
sizeof(000002773cb32d90) = 32 (0x20) bytes (System.Nullable`1[[System.Int32, mscorlib]][])

可以看到,一个是28byte,一个是32byte,多出来的就是那个hasValue哈,有一点要注意了,用!objsize打出来都是32byte,这是因为28byte要靠8对齐就变成32byte啦, 然后我把两个值类型转储出来,如下图:

到此,关于"C#可空类型原理是什么"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

代码 类型 就是 C# 字节 线程 原理 两个 内存 学习 也就是 更多 还是 演示 输出 地址 字段 方法 机器 空间 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 亿人帮互联网科技有限公司 深圳九邦互联网科技有限公司 互联网科技工作委员会主任 互联网核心科技是什么 互联网 的科技创新 互联网 视角下的科技创新 互联网高科技股票 海南购全球互联网科技 太原新华互联网科技学校怎么样 深圳前海聚择互联网科技有限公司 广州慧亚互联网科技怎么样 坤平互联网科技 佛山市拉法互联网科技有限公司 黑云互联网科技有限公司 图游互联网科技 昆明中奇联合互联网科技 青岛易易互联网科技 亚光科技低轨卫星互联网 互联网领先科技成果宣传视频 平安好医生打造互联网科技医疗 疫情对互联网科技公司影响 南京欣网互联网科技 百单互联网科技有限公司 碳银互联网科技有限公司 互联网科技网站 企晟互联网信息科技有限公司 互联网科技圈年度人物 上海万顺科技互联网有限公司招聘 互联网领先科技活动 互联网科技大佬云集
0