object在绝大多数场景下比dynamic快,尤其高频访问时性能差距达2–5倍;因dynamic需dlr运行时绑定,而object仅指针拷贝与类型校验。

直接说结论:object 在绝大多数场景下比 dynamic 快,尤其在高频访问、循环内调用或属性/方法频繁解析时,性能差距可达 2–5 倍;但这个差距只在「被反复调用的动态绑定点」上显著,单次使用几乎感知不到。
为什么 dynamic 比 object 慢?关键在 DLR 绑定开销
dynamic 不是“类型自由”,而是把类型解析工作从编译期拖到运行时,并依赖 DLR(Dynamic Language Runtime)完成成员查找、重载解析、调用绑定等一整套流程。每次访问 dyn.Property 或调用 dyn.Method(),CLR 都要:
- 检查调用点缓存(Call Site Cache)是否已存在匹配绑定
- 若未命中,触发动态绑定器(
Microsoft.CSharp.RuntimeBinder)执行符号解析 - 生成并缓存委托(通常是
Action或Func),供后续复用
而 object 的转换(如 (string)obj)只是指针拷贝 + 类型校验(is / as)或装箱/拆箱——这些是 JIT 优化得极好的底层操作,无反射或绑定层开销。
真实性能对比:循环中访问 Length 属性
以下代码片段在 .NET 6+ Release 模式下实测(100 万次迭代):
// object 版本(需转换) object obj = "test"; for (int i = 0; i <p>注意:<code>dynamic</code> 的第一次调用最慢(冷启动绑定),后续会走缓存,但缓存本身有哈希查找和委托调用跳转成本,仍高于静态调用路径。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2795" title="C#"><img src="https://img.php.cn/upload/skill/000/000/081/178936933912641.jpg" alt="C#" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill2795" title="C#" class="overflowclass">C#</a> <p class="overflowclass">"避开 C# 常见错误——空陷阱、异步陷阱、LINQ 陷阱及资源泄漏。"</p> </div> <a rel="nofollow" href="/xiazai/skill2795" title="C#" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <h3>哪些操作会让 dynamic 性能雪上加霜?</h3> <p>以下行为会显著放大 <code>dynamic</code> 的性能劣势,应避免在热路径中使用:</p>
- 在
for/foreach循环内部访问dynamic成员(尤其是属性或无参方法) - 将
dynamic作为泛型参数传递(如List<dynamic></dynamic>合法,但SomeMethod<t>(dynamicValue)</t>编译失败,强行绕过会引入隐式装箱) - 对
dynamic做大量==、+等运算符重载解析(每种运算都触发独立绑定) - 嵌套访问,如
dyn.User.Profile.Settings.Value(每级都是一次 DLR 绑定)
object 虽快,但装箱/拆箱也有代价
值类型(int、DateTime 等)赋给 object 会触发装箱(堆分配),取回时拆箱(类型检查 + 复制)。例如:
object boxed = 42; // 装箱:一次堆分配 int unboxed = (int)boxed; // 拆箱:类型检查 + 栈复制
这在高频小值类型场景下(如计数器、状态码)可能比 dynamic 更慢。此时更优解是:用泛型(T)、Span<t></t> 或直接避免中间 object 中转——dynamic 并不能解决这个问题,它只是把装箱延迟到了 DLR 层,反而多了一层开销。
真正影响性能的从来不是“用了 dynamic 还是 object”,而是“是否让运行时反复做同一件事”。高频动态访问必须预缓存(如提前转成具体类型或用 ExpandoObject + 字典索引),而不是依赖 DLR 每次现场查。










