Casting an object to IEnumerable where T is not known

后端 未结 2 603
生来不讨喜
生来不讨喜 2021-02-13 11:50

I am trying to play with Reflection and ran into the following situation.

In the following code, let\'s assume that the \'obj\' can be of types IEnumerable<>

相关标签:
2条回答
  • 2021-02-13 12:30

    Well, since you don't know the actual type of the items until runtime, you don't need to use the generic IEnumerable<T> interface; just use the non-generic one, IEnumerable (the generic one inherits from it):

    private void WriteGenericCollection(object obj)
    {
        IEnumerable enumerable = (IEnumerable)obj;
        foreach(object item in enumerable)
        {
            ...
        }
    }
    
    0 讨论(0)
  • 2021-02-13 12:35

    Your question is rife with misconceptions. Let's clear them up.

    In the following code, let's assume that the 'obj' can be of types IEnumerable<> or ICollection<> or IList<>.

    If that is true, and if you know the type of enumerable, a better way of writing the method would be

    private void WriteGenericCollection<T>(IEnumerable<T> obj)
    {
        // ...
    }
    

    I would like to downcast this System.Object to IEnumerable<> always (as ICollection<> and IList<> inherit from IEnumerable<> anyway), so that i would like to enumerate over the collection and use reflection to write the individual items.

    "Inherit" is not a correct term when talking about interfaces; it could also give you the wrong ideas. Interfaces are best thought of as contracts: when considering to implement an interface, you can only decide to implement it as the author intended or not implement it at all.

    Some interfaces are supersets of other interfaces; their contracts say "implementors must do this in addition to whatever else that contract says". But there is never any sharing of implementation as is common in inheritance, because interfaces do not have any.

    "Downcasting" is also not the correct term for what you are doing in that method. Downcasting means casting to a more derived class; there's also casting to an interface:

    // Note: the method is still generic!
    private void WriteGenericCollection<T>(object obj)
    {
        var casted = (IEnumerable<T>)obj;
    }
    

    I thought of downcasting the object to non-generic IEnumerable, but thought that this would cause unnecessary boxing of objects, when let's say the actual instance of IEnumerable...am I thinking right?

    Boxing would occur if and only if the object was an IEnumerable<T> where T is a value type (a numeric type, a bool, an enum or a struct). If the object implements IEnumerable<T> for some known T then you can simply cast it to that. If T is unknown then cast to non-generic IEnumerable and take the possible performance hit (there is no way around it in any case).

    You would only need to use reflection if you know nothing about the object (in which case of course you also need to have a plan for objects that cannot be enumerated, otherwise why allow passing them to your method in the first place?).

    0 讨论(0)
提交回复
热议问题