我正在查看一些非常有趣的代码。我试图理解它为什么有效。
控制器中的代码如下。
var paymentInfo = controllerService.GetPaymentSummary();
ViewBag.PaymentInfo = paymentInfo;
在控制器服务类中有这段代码。
public IEnumerable<SomeType> GetPaymentSummary()
{
// ...
return paymentInfo; // is of type List<SomeType>
}
在视图中,有一段非常有趣的代码。
@if (ViewBag.PaymentInfo.Count > 0)
{
// do something..
}
视图使用属于
Count
的 List<T>
属性。这怎么可能?
例如,在控制器中,我无法编写
paymentInfo.Count
,因为 paymentInfo
的类型为 IEnumerable<SomeType>
。
我知道这与
ViewBag
的动态有关,但有人可以详细说明一下吗?
(这样想:
IEnumerable
只是一个契约,规定了方法的返回值(即 paymentInfo
)必须满足的某些要求。
paymentInfo
实际上是,是一个List
。由于 List
实现了 IEnumerable
,它也可以表现为并被视为 IEnumerable
,但它的运行时类型仍然是 List
。
使用
Dynamic
时,重要的不是指定的返回类型(IEnumerable
),而是实际的对象;所有检查的都是“这个对象是否包含成员Count
?”,并且由于List
有一个Count
,所以效果很好。
当然,如果
GetPaymentSummary()
在某个时刻发生变化,并返回 IEnumerable
的其他实现,且 not 不包含 Count
成员,则您的代码可能会崩溃。
以下评论反馈后更新:
您可以通过使用
.Any()
来避免这种情况:
@if (ViewBag.PaymentInfo.Any())
{
// do something..
}
这应该可以正常工作,因为
.Any()
是在 IEnumerable
中声明的,而不仅仅是在 List
中声明的。