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?

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" }

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.


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>.


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.


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.


2

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


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.