Mengonversi secara bebas antara List <T> dan IEnumerable <T>

103

Bagaimana cara mengubah a List<MyObject>menjadi an IEnumerable<MyObject>dan kemudian kembali lagi?

Saya ingin melakukan ini untuk menjalankan serangkaian pernyataan LINQ pada Daftar, misalnya Sort()

TK.
sumber
Ini adalah yang tercakup dalam pertanyaan ini stackoverflow.com/questions/31708/…
Yohanes

Jawaban:

148
List<string> myList = new List<string>();
IEnumerable<string> myEnumerable = myList;
List<string> listAgain = myEnumerable.ToList();
Tamas Czinege
sumber
30
Berhati-hatilah karena myEnumarable adalah instance objek yang sama dengan myList, tetapi listAgain bukan instance objek yang sama dengan myEnumerable. Bergantung pada apa yang ingin Anda lakukan dan apa myEnumerable itu, "List <string> listAgain = myEnumerable as List <string>;" mungkin lebih baik.
ChrisW
1
Chrisw: Oh ya, tentu saja Anda benar, tetapi antarmuka IEnumerable <T> tidak dapat diubah sehingga tidak akan menimbulkan masalah ke arah itu dan casting back hanya terasa kotor ketika Anda memiliki fungsi yang akan menjaga keamanan tipe.
Tamas Czinege
1
Anda juga bisa menggunakan objek myList asli. (Saya kira saya tidak benar-benar mengerti pertanyaannya)
sth
6
Hanya saja jika dia mengedit myList maka dia akan mengedit myEnumrable, tetapi jika dia mengedit listA lagi, dia tidak akan mengedit myEnumerable.
ChrisW
15
Jangan lupa using System.Linq;atau Anda tidak akan dapat ToList ()
Jason
21

A List<T>adalah IEnumerable<T>, jadi sebenarnya, tidak perlu 'mengubah' a List<T>menjadi IEnumerable<T>. Karena a List<T>adalah IEnumerable<T>, Anda cukup menetapkan a List<T>ke variabel tipe IEnumerable<T>.

Sebaliknya, tidak semua IEnumerable<T>adalah List<T>offcourse, jadi Anda harus memanggil ToList()metode anggota IEnumerable<T>.

Frederik Gheysels
sumber
4
Secara teknis, ToList adalah metode anggota System.Linq.Enumerable
Amy B
2
Saya pikir Anda bisa memasukkan IEnumerable on List seperti yang dikatakan David.
abatishchev
9

A List<T>sudah menjadi IEnumerable<T>, jadi Anda dapat menjalankan pernyataan LINQ langsung pada List<T>variabel Anda .

Jika Anda tidak melihat metode ekstensi LINQ seperti yang OrderBy()saya duga, itu karena Anda tidak memiliki using System.Linqarahan di file sumber Anda.

Anda perlu mengubah hasil ekspresi LINQ kembali menjadi List<T>secara eksplisit, meskipun:

List<Customer> list = ...
list = list.OrderBy(customer => customer.Name).ToList()
Dan Berindei
sumber
"Jika Anda tidak melihat metode ekstensi LINQ seperti OrderBy ()" Itu masalah saya, terima kasih.
RyPope
5

Selain: Perhatikan bahwa operator LINQ standar (seperti contoh sebelumnya) tidak mengubah daftar yang ada - list.OrderBy(...).ToList()akan membuat daftar baru berdasarkan urutan yang diurutkan ulang. Namun, cukup mudah untuk membuat metode ekstensi yang memungkinkan Anda menggunakan lambda dengan 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)));
}

Kemudian Anda dapat menggunakan:

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

Ini memperbarui daftar yang ada dengan cara yang sama seperti List<T>.Sortbiasanya.

Marc Gravell
sumber
Sedikit koreksi untuk pernyataan ini: operator LINQ standar tidak mengubah daftar yang ada; sebagai gantinya, mereka membuat IEnumerable baru yang berisi logika yang diperlukan untuk melakukan pekerjaan mereka. Namun, logika ini tidak benar-benar dijalankan hingga IEnumerator diminta.
Vojislav Stojkovic
@Vojislav - Saya bermaksud dalam konteks contoh sebelumnya yang diakhiri dengan ToList- Saya akan menjelaskan, meskipun.
Marc Gravell
1

Mengonversi List<T>menjadiIEnumerable<T>

List<T>implement IEnumerable<T>(dan banyak lainnya seperti IList<T>, ICollection<T>) oleh karena itu tidak perlu mengonversi List kembali ke IEnumerable karena sudah menjadi IEnumerable<T>.

Contoh:

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;

Anda juga bisa menggunakan Enumerable.AsEnumerable()metode

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

Mengonversi IEnumerable<T>menjadiList<T>

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

Ini berguna dalam Entity Framework .

Nipuna
sumber
0

Untuk mencegah duplikasi dalam memori, resharper menyarankan ini:

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

.ToList () mengembalikan daftar baru yang tidak bisa diubah. Jadi perubahan pada listAgain tidak mempengaruhi myList dalam jawaban @Tamas Czinege. Ini benar dalam kebanyakan kasus untuk setidaknya dua alasan: Ini membantu mencegah perubahan di satu area yang mempengaruhi area lain (kopling longgar), dan ini sangat mudah dibaca, karena kita seharusnya tidak mendesain kode dengan masalah kompiler.

Tetapi ada contoh tertentu, seperti berada dalam loop ketat atau bekerja pada sistem memori tertanam atau rendah, di mana pertimbangan compiler harus dipertimbangkan.

TamusJRoyce
sumber