Question

My application has a method that caches a value. I need a second method that check if the generic parameter of type T implements IEnumerable and not implements IList. If the answer is yes, the method should do a .ToList and cast it back to T (See comment in code example).

Can you tell me how I do the .ToList() to return a List casted to back to T? (Is it actually possible?)

Something like this:

public T ToListIfIEnumerable<T>(T value)
{
    var needToCovert = TypeImplementsGenericIEnumerableButNotGenericIList(value);

    if (!needToCovert)
    {
        return value;
    }

    // return value.ToList() <-- How to do that???
}

private bool TypeImplementsGenericIEnumerableButNotGenericIList<T>(T value)
{
    var type = value.GetType();

    var interfaces = type.GetInterfaces();
    var gi = typeof(IEnumerable<>);
    var gl = typeof(IList<>);

    // It would be better if the next lines did't compare strings!
    // Suggestions welcome...
    var implementsIEnumerable = interfaces.Any(
        i => i.IsGenericType && i.Name == gi.Name && i.Namespace == gi.Namespace);
    var implementsIList = interfaces.Any(
        i => i.IsGenericType && i.Name == gl.Name && i.Namespace == gl.Namespace);

    return implementsIEnumerable && !implementsIList;
}

Backgrond info: The object that uses the method does something like Lazy. Caching an IEnumerable makes not much sense in examples like: Enumerable.Range(1, 3).Select(i => Guid.NewGuid()) It does gives new Guid's every time you call it. That is why I would like to do a ToList().

Was it helpful?

Solution

Dynamic typing and overloading could help here, if you don't mind using dynamic:

object ConvertToListIfNecessary(dynamic input)
{
    return MaybeToList(input);
}

private IList<T> MaybeToList<T>(IEnumerable<T> input)
{
    return input.ToList();
}

private IList<T> MaybeToList<T>(IList<T> input)
{
    return input;
}

private object MaybeToList(object input)
{
    // Take whatever action you want if the input *doesn't* implement
    // IEnumerable<T>
}

Basically this gets the smarts behind dynamic to do the grungy reflection work for you. It may not be quite as quick as something that's hand-rolled, but it's likely to be much simpler to get right.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top