Когда использовать Cast () и Oftype () в Linq

211

Я знаю двух способов литья типов в IEnumerableС Arraylistв Linq и интересно , в каких случаях использовать их?

например

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

или

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

В чем разница между этими двумя методами и где я должен применять каждый случай?

Джордж Стокер
источник

Ответы:

322

OfType- вернуть только те элементы, которые можно безопасно привести к типу x.
Cast- попытается привести все элементы к типу x. если некоторые из них не из этого типа вы получитеInvalidCastException

РЕДАКТИРОВАТЬ,
например:

object[] objs = new object[] { "12345", 12 };
objs.Cast<string>().ToArray(); //throws InvalidCastException
objs.OfType<string>().ToArray(); //return { "12345" }
Итай Каро
источник
1
ура за это. Пробовал оба заранее, но у обоих были все элементы ожидаемого типа, поэтому я не мог видеть разницу.
6
@SLaks правильно указывает, что вы должны использовать, Cast<T>когда точно знаете, что коллекция содержит только Tэлементы типа . OfType<T>медленнее из-за isпроверки типа. Если коллекция относится к типу IEnumerable<T>, Cast<T>просто приведёт всю коллекцию как IEnumerable<T>и избежать ее перечисления; OfType<T>все равно будет перечислять. ссылка: stackoverflow.com/questions/11430570/…
hIpPy
23
Даже в тех случаях, когда .Cast<string>()не выбрасывает при перечислении, это не эквивалентно .OfType<string>(). Причина в том, что nullзначения всегда пропускаются .OfType<TResult>(). Пример: new System.Collections.ArrayList { "abc", "def", null, "ghi", }.OfType<string>().Count()даст только 3; аналогичное выражение с .Cast<string>()вычисляет до 4.
Джепп Стиг Нильсен
1
другими словами, это что-то вроде разницы между операторами as и cast
faza
111

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

По сути, Cast () реализован так:

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

Использование явного приведения хорошо работает, но приведет к исключению InvalidCastException в случае сбоя приведения. Менее эффективный, но полезный вариант этой идеи - OfType ():

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

Возвращенное перечисление будет включать только элементы, которые можно безопасно привести к указанному типу.

ясень
источник
38

Вам следует позвонить, Cast<string>()если вы знаете, что все предметы strings.
Если некоторые из них не являются строками, вы получите исключение.

Вам следует позвонить, OfType<string>()если вы знаете, что некоторые предметы не принадлежат stringвам, и вам не нужны эти предметы.
Если некоторые из них не являются строками, они не будут в новом IEnumerable<string>.

SLaks
источник
1
Этот ответ (в настоящее время) единственный, который дает четкий совет, когда использовать какой метод.
CodeFox
4

Следует отметить, что Cast(Of T)его можно использовать в IEnumerableотличие от других функций LINQ, поэтому, если когда-либо понадобится использовать LINQ для неуниверсальной коллекции или списка, такого как ArrayList, вы можете использовать Cast(Of T)для приведения к тому IEnumerable(Of T)месту, где может работать LINQ.

Ния
источник
2

Cast()попытается привести все элементы коллекции (и выдаст исключение, если элемент имеет неправильный тип), в то время как OfType()вернет только элементы правильного типа.

Андрей Беззуб
источник
2

OfTypeотфильтрует элементы, чтобы вернуть только элементы указанного типа. Castпотерпит крах, если элемент не может быть приведен к целевому типу.

Иоганн Блэйс
источник
2

Cast<T>постараюсь привести все предметы к данному типу T. Это приведение может завершиться неудачей или вызвать исключение. OfType<T>вернет подмножество исходной коллекции и вернет только объекты, имеющие тип T.

Брайан Энсинк
источник