C#中dynamic是否装箱引发的思考

科技资讯 投稿 49500 0 评论

C#中dynamic是否装箱引发的思考

装箱拆箱

首先咱们先来看下何为装箱拆箱,这个可以在微软官方文档中Boxing and Unboxing文档中看到答案,咱们就简单的摘要一下相关的描述。

翻译起来会比较抽象,理解起来就是利用装箱和拆箱功能,可通过允许值类型的任何值与Object 类型的值相互转换,将值类型与引用类型链接起来。也就是值类型和引用类型相互转换的一做桥梁,但是问题也很明显那就是实例会存在在堆栈之前相互copy的问题,会存在一定的性能问题,所以这也一直是一个诟病。

探究本质

上面讲解了关于的概念,接下来咱们就来定义一段代码看看效果,为了方便对比咱们直接对比着看一下

dynamic num = 123;
dynamic str = "a string";

想要看清本质还是要反编译一下生成的结果看一下的,这里我们可以借助或来看下,首先看一下反编译回来的效果

private static void <Main>$(string[] args
{
	object num = 123;
	object str = "a string";
	Console.ReadKey(;
}

因为我是使用的是.net6的顶级声明方式所以会生成方法。不过从反编译的结果就可以看出来,如果还有点怀疑的话可以直接查看生成的代码,还是使用工具

.method private hidebysig static 
	void '<Main>$' (
		string[] args
	 cil managed 
{
	// Method begins at RVA 0x2094
	// Header size: 12
	// Code size: 30 (0x1e
	.maxstack 1
	.entrypoint
	.locals init (
        // 这里可以看出声明的num和str变量都是object类型的
		[0] object num,
		[1] object str
	

	// object obj = 123;
	IL_0000: ldc.i4.s 123
    // 这里的box说明存在装箱操作
	IL_0002: box [System.Runtime]System.Int32
	IL_0007: stloc.0
	// object obj2 = "a string";
	IL_0008: ldstr "a string"
	IL_000d: stloc.1
	// Console.ReadKey(;
	IL_000e: call valuetype [System.Console]System.ConsoleKeyInfo [System.Console]System.Console::ReadKey(
	IL_0013: pop
	// (no C# code
	IL_0014: nop
	IL_0015: nop
	IL_0016: nop
	IL_0017: nop
	IL_0018: nop
	IL_0019: nop
	IL_001a: nop
	IL_001b: nop
	// }
	IL_001c: nop
	IL_001d: ret
} // end of method Program::'<Main>$'

通过这里可以看出,既然是object那就可以证实确实是存在装箱操作。

这个其实在微软官方文档Using type dynamic上有说明,大致描述是这样的。

从这里可以看出dynamic表现出来的就是object,只是dynamic会跳过静态类型检查,所以编译的时候不会报错,有错误的话会在运行的时候报错,也就是我们说的是在运行时确定具体操作。这涉及到动态语言运行时,动态语言运行时(DLR是一种运行时环境,可以将一组动态语言服务添加到公共语言运行时(CLR。使用DLR可以轻松开发在.NET上运行的动态语言,并为静态类型语言添加动态特征。

匿名类型

var num = 123;
num = "123"; //报错

如果你是用的集成开发环境的话其实很容易发现,把鼠标放到类型上就会显示变量对应的真实类型。或者可以直接通过看看反编译结果,比如声明了编译完成之后就是

private static void <Main>$(string[] args
{
	int num = 123;
	Console.ReadKey(;
}

请注意这里并不是而是转换成了具体的类型因为就是int类型的,严谨一点看一下代码

.maxstack 1
.entrypoint
//声明的int32
.locals init (
	[0] int32 num

// int num = 123;
IL_0000: ldc.i4.s 123
IL_0002: stloc.0

相信这里就可以看出来了和确实也不是一个层面的东西。var是隐式类型是语法糖为了简化编程体验用的,dynamic则是动态语言运行时技术,编译时转换成object类型,因为在c#上一切都是object,然后再运行时进行具体的操作。

编程笔记 » C#中dynamic是否装箱引发的思考

赞同 (34) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽