Search code examples
c#asp.net-mvc

using IEnumerable<> as List<> when dynamic


I'm looking at some very interesting code. I am trying to understand why it works.

The code in the controller is as follows.

var paymentInfo = controllerService.GetPaymentSummary();
ViewBag.PaymentInfo = paymentInfo;

In the controller service class there is this code.

public IEnumerable<SomeType> GetPaymentSummary()
{
    // ...
    return paymentInfo; // is of type List<SomeType>
}

And in the View, there is this very interesting code.

@if (ViewBag.PaymentInfo.Count > 0)
{
    // do something..
}

The View makes use of Count property which belongs to List<T>. How is this possible?

In the controller, for example, I cannot write paymentInfo.Count because paymentInfo is of type IEnumerable<SomeType>.

I understand that this has something to do with ViewBag being dynamic, but could someone elaborate please?


Solution

  • (Think of it this way:

    IEnumerable is just a contract, stating certain requirements that the return value from your method (that is paymentInfo) must have.

    What paymentInfo actually is, is a List. Since List implements IEnumerable, it can also behave as and be treated as an IEnumerable, but it's runtime type is still List.

    When using Dynamic, what is important is not the specified return type (IEnumerable), but the actual object; All that is checked is "does this object contain a member Count?", and since List has a Count, this works out fine.

    Of course, if GetPaymentSummary() should change at some point, and return some other implementation of IEnumerable that does not contain a Count member, your code might break.

    Updated after feedback in a comment below:

    You can avoid that by using .Any() instead:

    @if (ViewBag.PaymentInfo.Any()) 
    {
        // do something..
    }
    

    This should work fine since .Any() is declared in IEnumerable, and not just in List.