Scott Baker
Scott Baker

Reputation: 10453

How Can I Retrieve the Underlying List of an IEnumerable Without Creating a New List?

When using IEnumerable I'm trying to avoid multiple enumerations. I know I can just use LINQ's .ToList() and be done with it, but that can be a lot of unnecessary list creation. I'd like to:

  1. check and see if the underlying type is a List, and if so return that instance, otherwise
  2. .ToList() it and return the new List

My thought was to use something akin to:

public void Fee()
{
    var list = new List<string>(); // I want to retrieve this instance in Foo
    Foo(list);
}

public void Foo(IEnumerable<T> enumerable)
{  
    var list = enumerable as List<T> ?? enumerable.ToList();
    // do stuff with original list 
}

... but it appears from the documentation that the as operator just performs a cast, which would create a new List rather than returning the underlying one, would it not?

If so, how can I retrieve the underlying list instead of creating a new one?

Upvotes: 1

Views: 270

Answers (2)

Alexei Levenkov
Alexei Levenkov

Reputation: 100555

The as operator does not create a new list. It only checks type and perform cast if type is compatible.

The code in the post is logically correct and matches how many LINQ methods are implemented (for example see source of Enumerable.Count which casts to ICollection to see if it can skip enumeration of items).

Note that it is important to cast to correct generic version of list or maybe one of its interfaces - IList would work if you must use non-generic version. Beware of the fact that List<T> is not co/contra-variant and type must match exactly unlike in case of covariant IEnumerable<out T> where you can cast parameter to IEnumerable<TBase> if IEnumerable<TDerived> passed.

Upvotes: 3

Marco Salerno
Marco Salerno

Reputation: 5201

Maybe you wanted to do this:

public void Fee()
{
    var list = new List<string>(); // I want to retrieve this instance in Foo
    Foo(list);
}

public void Foo<T>(IEnumerable<T> enumerable)
{
    List<T> list = enumerable as List<T> ?? enumerable.ToList();
    // do stuff with original list 
}

Upvotes: 0

Related Questions