Kapan menggunakan Cast () dan Oftype () di Linq

211

Saya mengetahui dua metode tipe casting IEnumerabledari dari Arraylistdalam Linq dan bertanya-tanya dalam kasus apa untuk menggunakannya?

misalnya

IEnumerable<string> someCollection = arrayList.OfType<string>()

atau

IEnumerable<string> someCollection = arrayList.Cast<string>()

Apa perbedaan antara kedua metode ini dan di mana saya harus menerapkan setiap kasus?

George Stocker
sumber

Jawaban:

322

OfType- kembalikan hanya elemen yang bisa dilemparkan dengan aman ke tipe x.
Cast- akan mencoba untuk membuang semua elemen ke dalam tipe x. jika beberapa dari mereka bukan dari jenis ini, Anda akan mendapatkanInvalidCastException

EDIT
misalnya:

object[] objs = new object[] { "12345", 12 };
objs.Cast<string>().ToArray(); //throws InvalidCastException
objs.OfType<string>().ToArray(); //return { "12345" }
Itay Karo
sumber
1
bersorak untuk itu. Mencoba keduanya sebelumnya tetapi keduanya memiliki elemen semua tipe yang diharapkan maka mengapa saya tidak bisa melihat perbedaannya.
6
@SLaks menunjukkan dengan benar bahwa Anda harus menggunakan Cast<T>ketika Anda tahu pasti bahwa koleksi hanya berisi Telemen tipe . OfType<T>lebih lambat karena ispemeriksaan tipe. Jika koleksinya berjenis IEnumerable<T>, Cast<T>cukup masukkan seluruh koleksi sebagai IEnumerable<T>dan hindari penghitungannya; OfType<T>masih akan disebutkan. ref: stackoverflow.com/questions/11430570/…
hIpPy
23
Bahkan dalam kasus di mana .Cast<string>()tidak melempar ketika disebutkan, itu tidak setara dengan .OfType<string>(). Alasannya adalah bahwa nullnilai selalu dilewati .OfType<TResult>(). Contoh: new System.Collections.ArrayList { "abc", "def", null, "ghi", }.OfType<string>().Count()hanya akan memberi 3; ekspresi serupa dengan .Cast<string>()evaluate to 4.
Jeppe Stig Nielsen
1
dengan kata lain, ini seperti perbedaan antara operator 'as' dan 'cast'
faza
111

http://solutionizing.net/2009/01/18/linq-tip-enumerable-oftype/

Pada dasarnya, Cast () diimplementasikan seperti ini:

public IEnumerable<T> Cast<T>(this IEnumerable source)
{
  foreach(object o in source)
    yield return (T) o;
}

Menggunakan gips eksplisit berkinerja baik, tetapi akan menghasilkan InvalidCastException jika gips gagal. Variasi yang kurang efisien namun bermanfaat pada ide ini adalah OfType ():

public IEnumerable<T> OfType<T>(this IEnumerable source)
{
  foreach(object o in source)
    if(o is T)
      yield return (T) o;
}

Pencacahan yang dikembalikan hanya akan mencakup elemen yang dapat dengan aman dilemparkan ke jenis yang ditentukan.

Abu
sumber
38

Anda harus menelepon Cast<string>()jika Anda tahu bahwa semua item adalah strings.
Jika beberapa dari mereka bukan string, Anda akan mendapatkan pengecualian.

Anda harus menelepon OfType<string>()jika Anda tahu bahwa beberapa item tidak stringdan Anda tidak ingin item itu.
Jika beberapa dari mereka bukan string, mereka tidak akan di yang baru IEnumerable<string>.

Slaks
sumber
1
Jawaban ini (saat ini) adalah satu-satunya yang memberikan saran eksplisit kapan harus menggunakan metode mana.
CodeFox
4

Perlu dicatat bahwa Cast(Of T)dapat digunakan pada IEnumerabletidak seperti fungsi LINQ lainnya, jadi jika ada kasus di mana Anda perlu menggunakan LINQ pada koleksi atau daftar non-generik seperti ArrayList, Anda dapat menggunakan Cast(Of T)untuk melemparkan ke IEnumerable(Of T)tempat LINQ dapat bekerja.

Niya
sumber
2

Cast()akan mencoba untuk membuang semua elemen koleksi (dan akan mengeluarkan pengecualian jika elemen dari tipe yang salah) sementara OfType()akan mengembalikan hanya elemen dengan tipe yang tepat.

Andrew Bezzub
sumber
2

OfTypeakan memfilter elemen untuk mengembalikan hanya yang dari tipe yang ditentukan. Castakan macet jika suatu elemen tidak dapat dilemparkan ke tipe target.

Johann Blais
sumber
2

Cast<T>akan mencoba untuk melemparkan semua item ke jenis yang diberikan T. Pemain ini bisa gagal atau melempar pengecualian. OfType<T>akan mengembalikan sebagian koleksi asli dan hanya mengembalikan objek yang bertipe T.

Brian Ensink
sumber