Quando utilizzare Cast () e Oftype () in Linq


211

Sono a conoscenza di due metodi di tipi di casting IEnumerableda aArraylist in Linq e mi chiedo in quali casi utilizzarli?

per esempio

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

o

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

Qual è la differenza tra questi due metodi e dove devo applicare ogni caso?

Risposte:


322

OfType- restituisce solo gli elementi che possono essere tranquillamente lanciati nel tipo x.
Cast- proverà a trasmettere tutti gli elementi nel tipo x. se alcuni di loro non sono di questo tipo, otterraiInvalidCastException

MODIFICA
ad esempio:

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

1
salute per quello. Ho provato entrambi in anticipo, ma entrambi avevano elementi tutti del tipo previsto, quindi perché non riuscivo a vedere la differenza.

6
@SLaks indica correttamente che dovresti usare Cast<T>quando sai per certo che la raccolta contiene solo Telementi di tipo . OfType<T>è più lento a causa del iscontrollo del tipo. Se la raccolta è di tipo IEnumerable<T>, Cast<T>eseguirà semplicemente il cast dell'intera raccolta IEnumerable<T>ed eviterà di enumerarla; OfType<T>enumererà ancora. ref: stackoverflow.com/questions/11430570/...
Hippy

23
Anche nei casi in cui .Cast<string>()non viene generato quando è elencato, non è equivalente a .OfType<string>(). Il motivo è che i nullvalori vengono sempre ignorati .OfType<TResult>(). Un esempio: new System.Collections.ArrayList { "abc", "def", null, "ghi", }.OfType<string>().Count()darà solo 3; l'espressione simile con .Cast<string>()valuta 4.
Jeppe Stig Nielsen,

1
in altre parole, è qualcosa di simile alla differenza tra operatori 'as' e 'cast'
faza

111

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

Fondamentalmente, Cast () è implementato in questo modo:

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

L'uso di un cast esplicito funziona bene, ma si tradurrà in una InvalidCastException se il cast fallisce. Una variante meno efficiente ma utile su questa idea è OfType ():

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

L'enumerazione restituita includerà solo elementi che possono essere trasmessi in modo sicuro al tipo specificato.


38

Dovresti chiamare Cast<string>()se sai che tutti gli articoli sono strings.
Se alcuni di essi non sono stringhe, otterrai un'eccezione.

Dovresti chiamare OfType<string>()se sai che alcuni degli articoli non sono stringse non li desideri.
Se alcuni di loro non sono stringhe, non saranno nel nuovo IEnumerable<string>.


1
Questa risposta è (attualmente) l'unica che fornisce un consiglio esplicito su quando utilizzare quale metodo.
CodeFox,

4

Va notato che Cast(Of T)può essere usato IEnumerablediversamente dalle altre funzioni LINQ, quindi se c'è un caso in cui è necessario utilizzare LINQ su una raccolta o un elenco non generico come un ArrayList, è possibile utilizzare Cast(Of T)per eseguire il cast in un luogo in IEnumerable(Of T)cui LINQ può funzionare.


2

Cast()proverà a eseguire il cast di tutti gli elementi della raccolta (e genererà un'eccezione se l'elemento è del tipo errato) mentre OfType()restituirà solo gli elementi del tipo corretto.


2

OfTypefiltrerà gli elementi per restituire solo quelli del tipo specificato. Castandrà in crash se un elemento non può essere lanciato sul tipo di destinazione.


2

Cast<T>proverà a trasmettere tutti gli oggetti al tipo specificato T. Questo cast potrebbe fallire o generare un'eccezione. OfType<T>restituirà un sottoinsieme della raccolta originale e restituirà solo oggetti di tipo T.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.