2014-09-23 33 views
0

我正在看一些非常有趣的代碼。我試圖理解它爲什麼起作用。使用IEnumerable <>作爲列表<>時動態

控制器中的代碼如下。

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.. 
} 

的視圖利用屬於List<T>Count財產。這怎麼可能?

在控制器中,例如,我不能寫paymentInfo.Count,因爲paymentInfo的類型爲IEnumerable<SomeType>

我明白,這與ViewBag是動態的,但有人可能會詳細說明嗎?

+8

嗯,你已經差不多自己說的。 'ViewBag'是'dynamic',所以包含它的表達式往往沒有編譯時類型檢查。相反,它們是動態解析的(基本上是通過反射),因此它們使用相關對象的運行時類型。 – 2014-09-23 20:40:50

+0

謝謝。我嘗試使用反射來獲取返回類型的'GetPaymentSummary()',它是'IEnumerable '。我猜在運行時發生了其他事情,因爲它看起來不同嗎? – erdinger 2014-09-23 21:00:02

+2

對象的運行時不是返回它的代碼的返回類型。運行時類型由哪個構造函數用來創建該特定對象(在運行時)來確定。因此,運行時類型永遠不是一個接口(比如'IEnumerable')。 – 2014-09-23 21:01:37

回答

6

認爲它是這樣的:

IEnumerable只是一個合同,說明您的方法(即paymentInfo)返回的值必須有一定的要求。

什麼paymentInfo實際上,是List。由於List實現IEnumerable,因此它也可以作爲並被視爲IEnumerable,但它的運行時類型仍然爲List

當使用Dynamic時,重要的不是指定的返回類型(IEnumerable),而是實際的對象;所有檢查的是「,這個對象是否包含一個成員Count」,並且由於List有一個Count,這工作得很好。

當然,如果GetPaymentSummary()應該在某個點更改,並返回其他一些實施IEnumerable,做包含Count成員,你的代碼可能會中斷。

你應該能夠做這樣的事情,如果你想解決的是:

var paymentInfoList = ViewBag.PaymentInfo.ToList(); // IEnumerable to List 
@if (paymentInfoList.Count > 0) 
{ 
    // do something.. 
} 
相關問題