Kiedy używać Cast () i Oftype () w Linq


211

Jestem świadomy dwóch metod rzutowania typów IEnumerablezArraylist Linq i zastanawiam się, w jakich przypadkach ich użyć?

na przykład

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

lub

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

Jaka jest różnica między tymi dwiema metodami i gdzie powinienem zastosować każdy przypadek?

Odpowiedzi:


322

OfType- zwraca tylko te elementy, które można bezpiecznie odlać do typu x.
Cast- spróbuje rzutować wszystkie elementy na typ x. jeśli niektóre z nich nie są z tego typu, dostanieszInvalidCastException

EDYCJA
na przykład:

object[] objs = new object[] { "12345", 12 };
objs.Cast<string>().ToArray(); //throws InvalidCastException
objs.OfType<string>().ToArray(); //return { "12345" }

1
na zdrowie. Próbowałem obu wcześniej, ale oba miały elementy, których oczekiwał cały typ, dlatego nie widziałem różnicy.

6
@SLaks prawidłowo wskazuje, że powinieneś używać, Cast<T>gdy wiesz na pewno, że kolekcja zawiera tylko Telementy typu . OfType<T>jest wolniejszy ze względu na iskontrolę typu. Jeśli kolekcja jest typu IEnumerable<T>, Cast<T>po prostu rzuci całą kolekcję jako IEnumerable<T>i uniknie jej wyliczenia; OfType<T>będzie nadal wyliczać. ref: stackoverflow.com/questions/11430570/…
hIpPy

23
Nawet w przypadkach, .Cast<string>()gdy nie rzuca się po wyliczeniu, nie jest równoważne z .OfType<string>(). Powodem jest to, że nullwartości są zawsze pomijane .OfType<TResult>(). Przykład: new System.Collections.ArrayList { "abc", "def", null, "ghi", }.OfType<string>().Count()da tylko 3; podobne wyrażenie z .Cast<string>()ocenia na 4.
Jeppe Stig Nielsen,

1
innymi słowy, jest to coś w rodzaju różnicy między operatorami „as” i „cast”
faza

111

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

Zasadniczo Cast () jest implementowany w następujący sposób:

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

Użycie jawnego rzutowania działa dobrze, ale spowoduje niepowodzenie InvalidCastException. Mniej wydajną, ale przydatną odmianą tego pomysłu jest OfType ():

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

Zwrócone wyliczenie będzie zawierało tylko elementy, które można bezpiecznie rzutować na określony typ.


38

Powinieneś zadzwonić, Cast<string>()jeśli wiesz, że wszystkie elementy są strings.
Jeśli niektóre z nich nie są łańcuchami, otrzymasz wyjątek.

Powinieneś zadzwonić, OfType<string>()jeśli wiesz, że niektóre elementy nie są stringi nie chcesz tych przedmiotów.
Jeśli niektóre z nich nie są łańcuchami, nie będą w nowym IEnumerable<string>.


1
Ta odpowiedź jest (obecnie) jedyną, która daje wyraźną poradę, kiedy użyć której metody.
CodeFox,

4

Należy zauważyć, że Cast(Of T)można go używać w IEnumerableodróżnieniu od innych funkcji LINQ, więc jeśli kiedykolwiek zajdzie potrzeba użycia LINQ w nieogólnej kolekcji lub liście, takiej jak an ArrayList, możesz użyć Cast(Of T)do rzutowania do miejsca, w IEnumerable(Of T)którym LINQ może działać.


2

Cast()spróbuje rzucić wszystkie elementy kolekcji (i wyrzuci wyjątek, jeśli element jest niewłaściwego typu), a OfType()zwróci tylko elementy właściwego typu.


2

OfTypeprzefiltruje elementy, aby zwrócić tylko te określonego typu. Castzawiesza się, jeśli elementu nie można rzutować na typ docelowy.


2

Cast<T>spróbuje rzucić wszystkie przedmioty na dany typ T. Ta obsada może zakończyć się niepowodzeniem lub zgłosić wyjątek. OfType<T>zwróci podzbiór oryginalnej kolekcji i zwróci tylko obiekty typu T.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.