106

How can I convert a List<MyObject> to an IEnumerable<MyObject> and then back again?

I want to do this in order to run a series of LINQ statements on the List, e. g. Sort()

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
TK.
  • 46,577
  • 46
  • 119
  • 147
  • This is the covered in this question http://stackoverflow.com/questions/31708/how-can-i-convert-ienumerablet-to-listt-in-c – John Mar 04 '10 at 15:59

6 Answers6

148
List<string> myList = new List<string>();
IEnumerable<string> myEnumerable = myList;
List<string> listAgain = myEnumerable.ToList();
Tamas Czinege
  • 118,853
  • 40
  • 150
  • 176
  • 31
    Beware however that myEnumarable is the same object instance as myList, but listAgain is not the same object instance as myEnumerable. Depending on what you want to do and what myEnumerable is, "List listAgain = myEnumerable as List;" might be better. – ChrisW Jan 23 '09 at 12:12
  • 1
    Chrisw: Oh yes, you're right of course, but the IEnumerable interface is immutable so it will not cause problems in that direction and casting back just feels *dirty* when you have a function that will take care of type safety. – Tamas Czinege Jan 23 '09 at 12:17
  • 1
    You also could just use the original myList object. (I guess I don't really get the question) – sth Jan 23 '09 at 12:27
  • 6
    It's just that if he edits myList then he would be editing myEnumrable, but if he edits listAgain then he wouldn't be editing myEnumerable. – ChrisW Jan 23 '09 at 12:28
  • 15
    Don't forget `using System.Linq;` or you won't be able to ToList() – Jason Apr 19 '12 at 04:25
  • Thanks @Blankasaurus. Normally, I rely on 'Resolve' to add any missing usings, but VS didn't offer this in the short-cut menu, even though I had a reference to System.Core. – R. Schreurs Aug 05 '13 at 13:55
  • @TamasCzinege calling .ToList() is definitely safer as you note, but it does of course come with a performance penalty (allocating the new list and copying the data to it). Sometimes performance considerations dictate dirtier code. – phoog Jun 04 '14 at 22:44
21

A List<T> is an IEnumerable<T>, so actually, there's no need to 'convert' a List<T> to an IEnumerable<T>. Since a List<T> is an IEnumerable<T>, you can simply assign a List<T> to a variable of type IEnumerable<T>.

The other way around, not every IEnumerable<T> is a List<T> offcourse, so then you'll have to call the ToList() member method of the IEnumerable<T>.

Amy B
  • 108,202
  • 21
  • 135
  • 185
Frederik Gheysels
  • 56,135
  • 11
  • 101
  • 154
9

A List<T> is already an IEnumerable<T>, so you can run LINQ statements directly on your List<T> variable.

If you don't see the LINQ extension methods like OrderBy() I'm guessing it's because you don't have a using System.Linq directive in your source file.

You do need to convert the LINQ expression result back to a List<T> explicitly, though:

List<Customer> list = ...
list = list.OrderBy(customer => customer.Name).ToList()
Dan Berindei
  • 7,054
  • 3
  • 41
  • 48
  • "If you don't see the LINQ extension methods like OrderBy()" That was my problem, thank you. – RyPope Mar 06 '14 at 22:13
5

Aside: Note that the standard LINQ operators (as per the earlier example) don't change the existing list - list.OrderBy(...).ToList() will create a new list based on the re-ordered sequence. It is pretty easy, however, to create an extension method that allows you to use lambdas with List<T>.Sort:

static void Sort<TSource, TValue>(this List<TSource> list,
    Func<TSource, TValue> selector)
{
    var comparer = Comparer<TValue>.Default;
    list.Sort((x,y) => comparer.Compare(selector(x), selector(y)));
}

static void SortDescending<TSource, TValue>(this List<TSource> list,
    Func<TSource, TValue> selector)
{
    var comparer = Comparer<TValue>.Default;
    list.Sort((x,y) => comparer.Compare(selector(y), selector(x)));
}

Then you can use:

list.Sort(x=>x.SomeProp); // etc

This updates the existing list in the same way that List<T>.Sort usually does.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • A slight correction to this statement: the standard LINQ operators don't change the existing list; instead, they create a new IEnumerable that contains the logic necessary for doing their work. However, this logic isn't actually executed until the IEnumerator is requested. – Vojislav Stojkovic Jan 23 '09 at 13:11
  • @Vojislav - I was meaning in the context of the earlier example ending with `ToList` - I will clarify, though. – Marc Gravell Jan 23 '09 at 13:12
1

Converting List<T> to IEnumerable<T>

List<T> implements IEnumerable<T> (and many other such as IList<T>, ICollection<T>) therefore there is no need to convert a List back to IEnumerable since it already a IEnumerable<T>.

Example:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Person person1 = new Person() { Id = 1, Name = "Person 1" };
Person person2 = new Person() { Id = 2, Name = "Person 2" };
Person person3 = new Person() { Id = 3, Name = "Person 3" };

List<Person> people = new List<Person>() { person1, person2, person3 };

//Converting to an IEnumerable
IEnumerable<Person> IEnumerableList = people;

You can also use Enumerable.AsEnumerable() method

IEnumerable<Person> iPersonList = people.AsEnumerable();

Converting IEnumerable<T> to List<T>

IEnumerable<Person> OriginallyIEnumerable = new List<Person>() { person1, person2 };
List<Person> convertToList = OriginallyIEnumerable.ToList();

This is useful in Entity Framework.

Nipuna
  • 6,846
  • 9
  • 64
  • 87
0

To prevent duplication in memory, resharper is suggesting this:

List<string> myList = new List<string>();
IEnumerable<string> myEnumerable = myList;
List<string> listAgain = myList as List<string>() ?? myEnumerable.ToList();

.ToList() returns a new immutable list. So changes to listAgain does not effect myList in @Tamas Czinege answer. This is correct in most instances for least two reasons: This helps prevent changes in one area effecting the other area (loose coupling), and it is very readable, since we shouldn't be designing code with compiler concerns.

But there are certain instances, like being in a tight loop or working on an embedded or low memory system, where compiler considerations should be taken into consideration.

TamusJRoyce
  • 817
  • 1
  • 12
  • 25