Wann werden Cast () und Oftype () in Linq verwendet?

211

Ich kenne zwei Methoden, um Typen IEnumerablevon einem Arraylistin Linq zu gießen und mich zu fragen, in welchen Fällen ich sie verwenden soll.

z.B

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

oder

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

Was ist der Unterschied zwischen diesen beiden Methoden und wo soll ich jeden Fall anwenden?

George Stocker
quelle

Antworten:

322

OfType- Geben Sie nur die Elemente zurück, die sicher in Typ x umgewandelt werden können.
Cast- wird versuchen, alle Elemente in Typ x umzuwandeln. Wenn einige von ihnen nicht von diesem Typ sind, erhalten SieInvalidCastException

BEARBEITEN
zum Beispiel:

object[] objs = new object[] { "12345", 12 };
objs.Cast<string>().ToArray(); //throws InvalidCastException
objs.OfType<string>().ToArray(); //return { "12345" }
Itay Karo
quelle
1
Prost dafür. Versuchte beide vorher, aber beide hatten Elemente des erwarteten Typs, weshalb ich den Unterschied nicht sehen konnte.
6
@SLaks weist korrekt darauf hin, dass Sie verwenden sollten, Cast<T>wenn Sie sicher sind, dass die Auflistung nur Typelemente enthält T. OfType<T>ist aufgrund der isTypprüfung langsamer . Wenn die Sammlung vom Typ ist IEnumerable<T>, Cast<T>wird einfach die gesamte Sammlung als gegossen, IEnumerable<T>und es wird vermieden, sie aufzuzählen. OfType<T>wird noch aufzählen. ref: stackoverflow.com/questions/11430570/…
hIpPy
23
Selbst in Fällen, in denen .Cast<string>()nicht geworfen wird, wenn es aufgezählt wird, ist es nicht gleichbedeutend mit .OfType<string>(). Der Grund ist, dass nullWerte immer übersprungen werden .OfType<TResult>(). Ein Beispiel: new System.Collections.ArrayList { "abc", "def", null, "ghi", }.OfType<string>().Count()wird nur geben 3; der ähnliche Ausdruck mit .Cast<string>()ergibt 4.
Jeppe Stig Nielsen
1
Mit anderen Worten, es ist so etwas wie der Unterschied zwischen '
as'-
111

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

Grundsätzlich ist Cast () folgendermaßen implementiert:

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

Die Verwendung einer expliziten Umwandlung funktioniert gut, führt jedoch zu einer InvalidCastException, wenn die Umwandlung fehlschlägt. Eine weniger effiziente und dennoch nützliche Variante dieser Idee ist OfType ():

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

Die zurückgegebene Aufzählung enthält nur Elemente, die sicher in den angegebenen Typ umgewandelt werden können.

Asche
quelle
38

Sie sollten anrufen, Cast<string>()wenn Sie wissen, dass alle Elemente strings sind.
Wenn einige von ihnen keine Zeichenfolgen sind, erhalten Sie eine Ausnahme.

Sie sollten anrufen, OfType<string>()wenn Sie wissen, dass einige der Elemente nicht strings sind und Sie diese Elemente nicht möchten.
Wenn einige von ihnen keine Zeichenfolgen sind, werden sie nicht in der neuen sein IEnumerable<string>.

SLaks
quelle
1
Diese Antwort ist (derzeit) die einzige, die explizit angibt, wann welche Methode anzuwenden ist.
CodeFox
4

Es sollte beachtet werden, dass Cast(Of T)dies im IEnumerableGegensatz zu anderen LINQ-Funktionen verwendet werden kann. Wenn Sie also jemals LINQ für eine nicht generische Sammlung oder Liste wie eine verwenden müssen ArrayList, können Sie diese Cast(Of T)in eine Funktion IEnumerable(Of T)umwandeln, in der LINQ funktionieren kann.

Niya
quelle
2

Cast()wird versuchen, alle Elemente der Sammlung zu konvertieren (und eine Ausnahme auslösen, wenn das Element vom falschen Typ ist), während OfType()nur Elemente vom richtigen Typ zurückgegeben werden.

Andrew Bezzub
quelle
2

OfTypefiltert die Elemente so, dass nur diejenigen des angegebenen Typs zurückgegeben werden. Caststürzt ab, wenn ein Element nicht in den Zieltyp umgewandelt werden kann.

Johann Blais
quelle
2

Cast<T>wird versuchen, alle Gegenstände auf den angegebenen Typ zu übertragen T. Diese Besetzung könnte fehlschlagen oder eine Ausnahme auslösen. OfType<T>gibt eine Teilmenge der ursprünglichen Sammlung zurück und gibt nur Objekte vom Typ zurück T.

Brian Ensink
quelle