Cuándo usar Cast () y Oftype () en Linq

211

Conozco dos métodos de conversión de tipos IEnumerabledesdeArraylist en Linq y me pregunto en qué casos usarlos.

p.ej

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

o

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

¿Cuál es la diferencia entre estos dos métodos y dónde debo aplicar cada caso?

George Stocker
fuente

Respuestas:

322

OfType- devuelve solo los elementos que se pueden convertir de forma segura a tipo x.
Cast- intentará convertir todos los elementos en tipo x. si algunos de ellos no son de este tipo, obtendráInvalidCastException

EDITAR
por ejemplo:

object[] objs = new object[] { "12345", 12 };
objs.Cast<string>().ToArray(); //throws InvalidCastException
objs.OfType<string>().ToArray(); //return { "12345" }
Itay Karo
fuente
1
aplausos por eso. Intenté ambos de antemano, pero ambos tenían elementos del tipo esperado, por lo tanto, no podía ver la diferencia.
66
@SLaks señala correctamente que debe usar Cast<T>cuando sabe con certeza que la colección contiene solo Telementos de tipo . OfType<T>es más lento debido a la isverificación de tipo. Si la colección es de tipo IEnumerable<T>, Cast<T>simplemente emitirá toda la colección como IEnumerable<T>y evitará enumerarla; OfType<T>seguirá enumerando. ref: stackoverflow.com/questions/11430570/…
hIpPy
23
Incluso en los casos en .Cast<string>()que no se lanza cuando se enumera, no es equivalente a .OfType<string>(). La razón es que los nullvalores siempre se omiten .OfType<TResult>(). Un ejemplo: new System.Collections.ArrayList { "abc", "def", null, "ghi", }.OfType<string>().Count()solo dará 3; la expresión similar con .Cast<string>()evalúa a 4.
Jeppe Stig Nielsen
1
en otras palabras, es algo así como la diferencia entre los operadores 'as' y 'cast'
faza
111

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

Fundamentalmente, Cast () se implementa así:

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

El uso de una conversión explícita funciona bien, pero dará como resultado una InvalidCastException si la conversión falla. Una variación menos eficiente pero útil de esta idea es OfType ():

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

La enumeración devuelta solo incluirá elementos que se puedan convertir de forma segura en el tipo especificado.

Ceniza
fuente
38

Debe llamar Cast<string>()si sabe que todos los artículos son strings.
Si algunos de ellos no son cadenas, obtendrá una excepción.

Debe llamar OfType<string>()si sabe que algunos de los artículos no son stringsy no desea esos artículos.
Si algunos de ellos no son cadenas, no estarán en el nuevo IEnumerable<string>.

SLaks
fuente
1
Esta respuesta es (actualmente) la única que da un consejo explícito sobre cuándo usar qué método.
CodeFox
4

Cabe señalar que Cast(Of T)se puede usar a IEnumerablediferencia de otras funciones de LINQ, por lo que si alguna vez necesita usar LINQ en una colección o lista no genérica como ArrayList, puede usarlo Cast(Of T)para convertirlo en un lugar IEnumerable(Of T)donde LINQ pueda funcionar.

Niya
fuente
2

Cast()intentará lanzar todos los elementos de la colección (y lanzará una excepción si el elemento es del tipo incorrecto) mientras OfType()que solo devolverá elementos del tipo adecuado.

Andrew Bezzub
fuente
2

OfTypefiltrará los elementos para devolver solo los del tipo especificado. Castse bloqueará si un elemento no se puede lanzar al tipo de destino.

Johann Blais
fuente
2

Cast<T>intentará lanzar todos los elementos al tipo dado T. Este elenco podría fallar o arrojar una excepción. OfType<T>devolverá un subconjunto de la colección original y solo devolverá objetos de tipo T.

Brian Ensink
fuente