Quando usar Cast () e Oftype () no Linq

211

Estou ciente de dois métodos de conversão de tipos para IEnumerableum Arraylistno Linq e me pergunto em quais casos usá-los?

por exemplo

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

ou

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

Qual é a diferença entre esses dois métodos e onde devo aplicar cada caso?

George Stocker
fonte

Respostas:

322

OfType- retorne apenas os elementos que podem ser convertidos com segurança para o tipo x.
Cast- tentará converter todos os elementos no tipo x. se alguns deles não são desse tipo, você receberáInvalidCastException

EDITAR
por exemplo:

object[] objs = new object[] { "12345", 12 };
objs.Cast<string>().ToArray(); //throws InvalidCastException
objs.OfType<string>().ToArray(); //return { "12345" }
Itay Karo
fonte
1
um brinde por isso. Tentei ambos de antemão, mas ambos tinham elementos de todo o tipo esperado, portanto, por que eu não conseguia ver a diferença.
6
O @SLaks indica corretamente que você deve usar Cast<T>quando tiver certeza de que a coleção contém apenas Telementos de tipo . OfType<T>é mais lento devido à isverificação de tipo. Se a coleção for do tipo IEnumerable<T>, Cast<T>simplesmente converterá a coleção inteira como IEnumerable<T>e evitar enumerá-la; OfType<T>ainda enumerará. ref: stackoverflow.com/questions/11430570/…
hIpPy
23
Mesmo nos casos em que .Cast<string>()não é lançado quando é enumerado, não é equivalente a .OfType<string>(). O motivo é que os nullvalores são sempre ignorados .OfType<TResult>(). Um exemplo: new System.Collections.ArrayList { "abc", "def", null, "ghi", }.OfType<string>().Count()dará apenas 3; a expressão semelhante com .Cast<string>()avalia para 4.
Jeppe Stig Nielsen
1
em outras palavras, é algo parecido com a diferença entre operadores 'as' e 'cast'
20/02/19
111

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

Fundamentalmente, Cast () é implementado assim:

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

O uso de uma conversão explícita tem um bom desempenho, mas resultará em InvalidCastException se a conversão falhar. Uma variação menos eficiente e útil dessa ideia é OfType ():

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

A enumeração retornada incluirá apenas elementos que podem ser convertidos com segurança para o tipo especificado.

Cinza
fonte
38

Você deve ligar Cast<string>()se souber que todos os itens são strings.
Se alguns deles não forem strings, você receberá uma exceção.

Você deve ligar OfType<string>()se souber que alguns dos itens não são se stringvocê não os deseja.
Se alguns deles não são strings, eles não estarão no novo IEnumerable<string>.

SLaks
fonte
1
Essa resposta é (atualmente) a única que fornece conselhos explícitos quando usar qual método.
CodeFox 18/08/16
4

Deve-se notar que Cast(Of T)pode ser usado IEnumerablediferentemente de outras funções do LINQ, portanto, se houver um caso em que você precise usar o LINQ em uma coleção ou lista não genérica como uma ArrayList, você poderá usar Cast(Of T)para transmitir para um IEnumerable(Of T)local em que o LINQ possa funcionar.

Niya
fonte
2

Cast()tentará converter todos os elementos da coleção (e lançará uma exceção se o elemento for do tipo errado) enquanto OfType()retornará apenas elementos do tipo apropriado.

Andrew Bezzub
fonte
2

OfTypefiltrará os elementos para retornar apenas os do tipo especificado. Castfalhará se um elemento não puder ser convertido para o tipo de destino.

Johann Blais
fonte
2

Cast<T>tentará converter todos os itens para o tipo especificado T. Esse elenco pode falhar ou gerar uma exceção. OfType<T>irá retornar um subconjunto da coleção original e retornar apenas objetos que são do tipo T.

Brian Ensink
fonte