Quand utiliser Cast () et Oftype () dans Linq

211

Je connais deux méthodes pour lancer des types vers IEnumerableunArraylist dans Linq et je me demande dans quels cas les utiliser?

par exemple

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

ou

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

Quelle est la différence entre ces deux méthodes et où dois-je appliquer chaque cas?

George Stocker
la source

Réponses:

322

OfType- renvoyer uniquement les éléments pouvant être convertis en toute sécurité au type x.
Cast- va essayer de convertir tous les éléments en type x. si certains d'entre eux ne sont pas de ce type, vous obtiendrezInvalidCastException

MODIFIER
par exemple:

object[] objs = new object[] { "12345", 12 };
objs.Cast<string>().ToArray(); //throws InvalidCastException
objs.OfType<string>().ToArray(); //return { "12345" }
Itay Karo
la source
1
bravo pour ça. J'ai essayé les deux à l'avance mais les deux avaient des éléments du type attendu, c'est pourquoi je ne pouvais pas voir la différence.
6
@SLaks souligne correctement que vous devez utiliser Cast<T>lorsque vous savez avec certitude que la collection ne contient que des Téléments de type . OfType<T>est plus lent en raison de la isvérification du type. Si la collection est de type IEnumerable<T>, Cast<T>elle transtypera simplement la collection entière en tant que IEnumerable<T>et évitera de l'énumérer; OfType<T>sera encore énumérer. ref: stackoverflow.com/questions/11430570/…
hIpPy
23
Même dans les cas où .Cast<string>()ne lance pas quand il est énuméré, ce n'est pas équivalent à .OfType<string>(). La raison en est que les nullvaleurs sont toujours ignorées .OfType<TResult>(). Un exemple: new System.Collections.ArrayList { "abc", "def", null, "ghi", }.OfType<string>().Count()ne donnera que 3; l'expression similaire à .Cast<string>()évalue à 4.
Jeppe Stig Nielsen
1
en d'autres termes, c'est quelque chose comme la différence entre les opérateurs 'as' et 'cast'
faza
111

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

Fondamentalement, Cast () est implémenté comme ceci:

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

L'utilisation d'un cast explicite fonctionne bien, mais entraînera une InvalidCastException si le cast échoue. OfType () est une variante moins efficace mais utile de cette idée:

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

L'énumération retournée inclura uniquement les éléments qui peuvent être convertis en toute sécurité dans le type spécifié.

Cendre
la source
38

Vous devriez appeler Cast<string>()si vous savez que tous les articles sont des stringart.
Si certains d'entre eux ne sont pas des chaînes, vous obtiendrez une exception.

Vous devriez appeler OfType<string>()si vous savez que certains éléments ne sont pas strings et que vous ne voulez pas ces éléments.
Si certains d'entre eux ne sont pas des chaînes, ils ne seront pas dans le nouveau IEnumerable<string>.

SLaks
la source
1
Cette réponse est (actuellement) la seule qui donne un conseil explicite sur l'utilisation de quelle méthode.
CodeFox
4

Il convient de noter que Cast(Of T)peut être utilisé sur IEnumerablecontrairement à d'autres fonctions LINQ, donc s'il y a un cas où vous devez utiliser LINQ sur une collection ou une liste non générique comme un ArrayList, vous pouvez utiliser Cast(Of T)pour effectuer un cast vers un IEnumerable(Of T)endroit où LINQ peut fonctionner.

Niya
la source
2

Cast()essaiera de transtyper tous les éléments de la collection (et lèvera une exception si l'élément est du mauvais type) tandis que OfType()ne retournera que les éléments de type approprié.

Andrew Bezzub
la source
2

OfTypefiltrera les éléments pour ne renvoyer que ceux du type spécifié. Castplantera si un élément ne peut pas être converti en type cible.

Johann Blais
la source
2

Cast<T>va essayer de lancer tous les éléments dans le type donné T. Cette conversion peut échouer ou lever une exception. OfType<T>renverra un sous-ensemble de la collection d'origine et renverra uniquement les objets de type T.

Brian Ensink
la source