商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C#怎么使用动态类型dynamic_C# dynamic运行时类型教程【高级】

C#怎么使用动态类型dynamic_C# dynamic运行时类型教程【高级】

  发布于2026-07-18 阅读(0)

扫一扫,手机访问

聊到 C# 的 dynamic,很多人第一反应是“运行时类型”,但这种理解其实不太对。它并不是运行时态,而更像是一张编译器给开的“后门通行证”。简单说,你把变量声明为 dynamic,编译器就不再检查你有没有写对成员名、参数个数对不对、能不能赋值——这些事全推到运行时,交给 DLR(动态语言运行时)去处理。要是用错了地方,直接甩你一个 RuntimeBinderException,连个调试的余地都不给。

什么场景非用 dynamic 不可?

关键不在于“能不能装任意值”,而在于“调用成员的时候要不要走 DLR 绑定”。你可以试试看,object 上调用方法直接编译不过去(除非你用反射),而 dynamic 会把整个调用链——方法名、参数、重载选择——打包成一个 CallSite,等到运行时才去查目标对象到底有没有那个方法。哪些场景非它不可?

  • 和 COM 对象打交道,比如 Excel 互操作,不想写一大串 Marshal.Invoke 或者 Type.InvokeMember
  • 接收来自 IronPython、Ruby.NET 这类动态语言的返回值,签名在 C# 编译期根本不知道
  • 解析 HTML DOM(比如 mshtmlMicrosoft.Office.Interop.Excel),属性名和方法名是字符串驱动的
  • 做高度泛化的 JSON 反序列化桥接,比如 Newtonsoft.Json.Linq.JObjectdynamic 后直接点属性

dynamic 赋值后类型变了吗?

这个要分清楚:变量本身类型始终是 dynamic,但所指向的底层值可以是任意类型。IntelliSense 显示的是声明类型,不是值类型。看个例子就明白了:

dynamic d = 42;
Console.WriteLine(d.GetType()); // System.Int32
d = "hello";
Console.WriteLine(d.GetType()); // System.String
d = new[] { 1, 2, 3 };
Console.WriteLine(d.GetType()); // System.Int32[]

这里 var 真代替不了。var d = 42; 推导出来是 int,后面不能再赋值字符串。但 dynamic 可以跨类型赋值,而且每次 .GetType() 返回的都是真实运行时类型。

为什么 dynamic_ec.exampleMethod1(10, 4) 是运行时抛异常而不是编译报错?

编译器对 dynamic 表达式的任何成员访问——方法、属性、索引器——都生成 CallSite,把调用信息缓存起来,等到第一次执行才尝试绑定。DLR 的查找顺序是这样的:

  • 看看目标对象有没有公开实例方法 exampleMethod1,并且参数个数、类型能隐式转换匹配
  • 查有没有扩展方法能用(需 using 命名空间已引入)
  • 查是否实现了 IDynamicMetaObjectProvider,走自定义绑定逻辑
  • 全部失败:抛 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException

所以即使 ExampleClass 只定义了 exampleMethod1(int i)dynamic_ec.exampleMethod1(10, 4) 还是会走到第 4 步失败,错误信息类似 'ExampleClass' does not contain a definition for 'exampleMethod1'

那些容易被忽略的性能与调试陷阱

dynamic 绑定的开销比想象中大。首次调用慢——要构建和缓存 CallSite;后续同签名调用快——命中缓存;但一旦参数类型组合发生变化(比如从 int 换成 long),又触发新绑定。更麻烦的是调试体验:

  • 断点停在 dynamic 行时,Locals 窗口只显示 dynamic,看不到实际值结构(得鼠标悬停或用 QuickWatch 输入 d.ToString()
  • 异常堆栈里看不到原始调用点,而是深埋在 Microsoft.CSharp.RuntimeBinder 内部
  • ReSharper 或 Roslyn 分析器做不了空引用或成员缺失预警
  • dynamic 传入泛型方法时,类型推导会失效:DoSomething(dynamicValue)T 会被推为 dynamic,而不是实际运行时类型

真正难缠的不是语法本身,而是你得想清楚:这个 dynamic 值从哪来、生命周期内可能是什么类型、谁负责保证它有你要调的方法。这些责任全移交给了程序员,编译器不再兜底。

本文转载于:https://www.php.cn/faq/2344499.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注