This is a bit difficult to explain. So here it goes.
I have a function like this:
public T FooBar<T>(Func<T> function)
{
T returnData = function();
// want to iterate through returnData to do something to it
return returnData;
}
If the returnData
(T) is an IEnumerable
list, then I would like to enumerate through returnData
to modify its contents using reflection. But I can't seem to be able to do it. When I try to cast returnData
to an enumerable type, I get an exception:
Unable to cast object of type
'System.Collections.Generic.List`1[Cars]'
to type
'System.Collections.Generic.List`1[System.Object]'.
I will not know that the return type will be a list of 'cars' for example ahead of time, only at run time. So I have to check using reflection if it is a list, and then try to cast it so that I can enumerate through it.
Unless I am going about it the wrong way. How can I enumerate through returnData
if it is of type T
?
Deferred Danger One of the many useful warnings in ReSharper is “Possible multiple enumeration of IEnumerable“. If you enumerate an enumerable more than once, ReSharper detects that and warns you about it. Although this warning may seem pointless at first, there are two good reasons to pay attention to it.
IEnumerable. IEnumerable<T> contains a single method that you must implement when implementing this interface; GetEnumerator, which returns an IEnumerator<T> object. The returned IEnumerator<T> provides the ability to iterate through the collection by exposing a Current property.
IEnumerable is an interface defining a single method GetEnumerator() that returns an IEnumerator interface. It is the base interface for all non-generic collections that can be enumerated. This works for read-only access to a collection that implements that IEnumerable can be used with a foreach statement.
One approach is to add a type constraint on T
, but this is not ideal:
public T FooBar<T>(Func<T> function) where T : IEnumerable
{
// T is not strongly typed for the enumerated item
If you changed your method slightly (w.r.t. T
):
public IEnumerable<T> FooBar<T>(Func<IEnumerable<T>> function)
Then you have strong typing on the actual item being enumerated with the added bonus of accepting enumerable objects.
So I noticed from a second read of your question, there is some confusion about what T
means for your variable returnData
. In the case where FooBar()
is passed a List<Car>
, T
is List<Car>
, and really has no association with the generic type specification of the List<>
itself. You can think of it as some List<U>
where U
is some other, unknown type.
At runtime you will have no simple way to get to U
as it is hidden, so to speak, inside T
. You could use overloading as some of the other answerers recommend, and provide a non-IEnumerable<U>
method and one which takes arguments of type Func<IEnumerable<T>>
.
Perhaps with some more details about the goal of FooBar<T>
we could make some more specific recommendations.
if (returnData is System.Collections.IEnumerable)
{
foreach (object o in (System.Collections.IEnumerable)returnData)
{
// Do something.
}
}
Really, though, why not have an additional overload like this:
public T FooBar<T>(Func<IEnumerable<T>> function)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With