我知道ViewData和ViewBag都使用相同的后台数据,但在大多数情况下,它们都不如使用强类型模型好。然而,在选择两者之间时,ViewBag的动态特性是否比使用ViewData更慢?
我知道ViewData和ViewBag都使用相同的后台数据,但在大多数情况下,它们都不如使用强类型模型好。然而,在选择两者之间时,ViewBag的动态特性是否比使用ViewData更慢?
好的,我的初始答案基本上是“不行”,现在需要做一个大转弯。
在完美动态世界中,理论上应该是“不行”的,但仔细检查后发现,除了考虑 JIT 魔法外,可能不会有任何区别,或者说可能会稍微慢一点点,但不足以不使用它(至少我是这么做的)。
从理论上讲,如果正确地实现,ViewBag 最终将优于使用 ViewData 字典,因为表达式的绑定(例如 ViewBag.Foo
)非常好地缓存于编译器生成的不同 CallSite 之间(反射一个读取或写入 ViewBag
的方法,你就会明白我的意思)。
DLR 的缓存层有很好的文档(深入理解起来有点困难),但基本上运行时会尽力“记住”绑定给定值实例的位置,例如通过 Set 或 Get 语句。
但是缓存、它的使用和有效性完全取决于类/接口的底层实现,例如 DynamicObject、IDynamicMetaObjectProvider 等,以及 Get/Set 表达式绑定的最终结果。
在 MVC 内部的 DynamicViewDataDictionary 类中,它最终绑定到此处:
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = this.ViewData[binder.Name];
return true;
}
对于 var a = ViewBag.Foo
以及
public override bool TrySetMember(SetMemberBinder binder, object value)
{
this.ViewData[binder.Name] = value;
return true;
}
对于ViewBag.Foo = Bar;
换句话说 - 这些语句实际上被重写为字典索引器的包装器。
因此,它肯定不能比自己手动执行更快。
如果ViewData
以ViewBag
为基础,并且使用类似ExpandoObject
这样的东西来实现ViewBag
,那么情况可能会有所不同 - 因为ExpandoObject
的动态实现要更加智能,它采用的缓存规则允许进行一些相当不错的运行时优化。
(感谢Shawn McLean建议需要这样一个结论!)
ViewBag
会比ViewData
慢;但可能不足以引起关注。
我没有做过任何测试,但我觉得在实际场景中,这种差异微不足道。你可能每个页面都会访问它几次,而且只有几个CPU周期不会有任何区别。我们可以在其他地方找到更大的性能提升。