C# 动态类型dynamic使用方法 C# dynamic关键字有什么用

来源:这里教程网 时间:2026-02-21 17:40:42 作者:

dynamic 和 var、object 到底差在哪?

dynamic
不是“更灵活的
var
”,也不是“带智能提示的
object
”——它是编译器主动放弃类型检查的明确信号。

var
是编译期推导,类型一旦确定就不可变(
var x = "a"; x = 123;
直接编译报错);
object
要访问成员必须显式转换(
((string)obj).Length
),IDE 能提示、能重构;
dynamic
所有成员访问、方法调用、运算符都跳过编译检查,全靠运行时 DLR 解析,写错
obj.Lengh
(拼错)也能过编译,直到执行才抛
RuntimeBinderException

什么场景真该用 dynamic?

它不是语法糖,而是为特定互操作瓶颈设计的“减压阀”。

✅ 和 COM 对象交互:比如
Excel.Application
,不用写一长串
Marshal.ReleaseComObject
InvokeMember
✅ 处理未知结构 JSON:用
Newtonsoft.Json.Linq.JObject
System.Text.Json.JsonNode
反序列化后,直接
data.users[0].name
访问;
✅ 包装反射调用:比如你有一堆
MethodInfo
调用逻辑,换成
dynamic obj = target; obj.DoSomething();
更直白;
✅ 构建脚本桥接层(如暴露 C# 方法给 Lua/Python 调用),配合
IDynamicMetaObjectProvider
实现自定义绑定。

❌ 别用在业务模型层、DTO 传输、循环内高频访问——性能损耗明显(DLR 缓存虽有,但首次解析开销大),且 IDE 完全失能。

怎么安全地用 dynamic?避免 runtime 崩溃

动态不等于随意,几个实操习惯能大幅降低风险:

永远在调用前用
obj is string
obj?.GetType() == typeof(int)
做类型守门;
对来自外部的数据(如 API JSON),优先用强类型反序列化;仅当 schema 真正多变、且字段数少时,才退到
dynamic
配合
ExpandoObject
构建可写动态对象时,注意
ExpandoObject
本身实现了
IDictionary<string object></string>
,可遍历属性名,方便做字段校验;
在调试时,直接在监视窗口输入
obj.GetType()
((IDynamicMetaObjectProvider)obj).GetMetaObject(Expression.Constant(obj))
查看当前绑定状态。

性能到底慢多少?要不要担心?

DLR 的首次调用比静态调用慢 5–10 倍(主要花在元数据查找和缓存构建上),后续同签名调用会命中缓存,差距缩小到 1.2–1.5 倍。

单次调用(如初始化 Excel、解析一个配置项)完全可忽略; 但在
for
循环里反复调用
item.Name
(其中
item
dynamic
)就会明显拖慢;
替代方案:用
Convert.ToString(item.Name)
或提前转成具体类型(
string name = item.Name;
),让后续访问回归静态路径。

真正容易被忽略的是调试成本——断点停住后,你没法靠鼠标悬停看属性,得手动敲

obj.GetType()
obj.ToString()
,甚至进“快速监视”查
IDynamicMetaObjectProvider
实现细节。这不是语法问题,是开发流被打断。

相关推荐