Apakah LINQ bekerja dengan IEnumerable?

87

Saya memiliki kelas yang mengimplementasikan IEnumerable, tetapi tidak menerapkan IEnumerable<T>. Saya tidak dapat mengubah kelas ini, dan saya tidak dapat menggunakan kelas lain sebagai gantinya. Seperti yang saya pahami dari MSDN LINQ dapat digunakan jika kelas mengimplementasikanIEnumerable<T> . Saya sudah mencoba menggunakan instance.ToQueryable(), tetapi masih tidak mengaktifkan metode LINQ. Saya tahu pasti bahwa kelas ini dapat berisi instance dari satu jenis saja, sehingga kelas tersebut dapat mengimplementasikannya IEnumerable<T>, tetapi sebenarnya tidak. Jadi apa yang dapat saya lakukan untuk menanyakan kelas ini menggunakan ekspresi LINQ?

Bogdan Verbenets
sumber
Tanpa mentransmisikan IEnumerable, alih-alih semua metode linq, Anda hanya akan melihat 8 metode: AsQuerable, Cast <>, Equals, GetEnumerator, GetHashCode, GetType, OfType <>, ToString
ShawnFeatherly

Jawaban:

136

Anda dapat menggunakan Cast<T>()atau OfType<T>mendapatkan versi umum dari IEnumerable yang sepenuhnya mendukung LINQ.

Misalnya.

IEnumerable objects = ...;
IEnumerable<string> strings = objects.Cast<string>();

Atau jika Anda tidak tahu jenis isinya, Anda selalu dapat melakukan:

IEnumerable<object> e = objects.Cast<object>();

Jika non-generik Anda IEnumerableberisi objek dari berbagai jenis dan Anda hanya tertarik misalnya. string yang dapat Anda lakukan:

IEnumerable<string> strings = objects.OfType<string>();
Kopi bebas kafein
sumber
2
Setiap hari, saya belajar sesuatu yang baru tentang LINQ. Setiap hari, saya semakin menyukainya.
João Mendes
11

Ya itu bisa. Anda hanya perlu menggunakan Cast<T>fungsi tersebut untuk mengubahnya menjadi diketik IEnumerable<T>. Sebagai contoh:

IEnumerable e = ...;
IEnumerable<object> e2 = e.Cast<object>();

Sekarang e2adalah IEnumerable<T>dan dapat bekerja dengan semua fungsi LINQ.

JaredPar
sumber
3

Anda juga dapat menggunakan sintaks pemahaman kueri LINQ, yang mentransmisikan ke tipe variabel rentang ( itemdalam contoh ini) jika sebuah tipe ditentukan:

IEnumerable list = new ArrayList { "dog", "cat" };

IEnumerable<string> result =
  from string item in list
  select item;

foreach (string s in result)
{
    // InvalidCastException at runtime if element is not a string

    Console.WriteLine(s);
}

Efeknya identik dengan solusi @ JaredPar; lihat 7.16.2.2: Jenis Variabel Rentang Eksplisit dalam spesifikasi bahasa C # untuk detailnya.

TrueWill
sumber