Использование синтаксиса метода расширения LINQ в MatchCollection

92

У меня такой код:

MatchCollection matches = myRegEx.Matches(content);

bool result = (from Match m in matches
               where m.Groups["name"].Value.Length > 128
               select m).Any();

Есть ли способ сделать это с помощью синтаксиса метода расширения LINQ?

Что-то вроде этого:

bool result = matches.Any(x => ... );
Томас
источник

Ответы:

196
using System.Linq;

matches.Cast<Match>().Any(x => x.Groups["name"].Value.Length > 128)

Вам просто нужно , чтобы преобразовать ее из IEnumerableк IEnumerable<Match>(IEnumerable <T>) , чтобы получить доступ к расширению LINQ , представленной на IEnumerable <T>.

msarchet
источник
Кто здесь голосует против каждого ответа? Этот ответ получил мою поддержку, друзья.
Кевин Калитовски 01
+1 Я пытаюсь понять, почему это было отклонено. Я этого не вижу.
Джейсон 01
Я действительно сбит с толку, как за это проголосовали, поскольку это правильно
msarchet 01
1
Это работает, просто убедитесь, что вы, using System.Linqиначе это выдаст синтаксическую ошибку
Эш Берлин-Тейлор,
1
Спасибо всем, кто запутался, Castне нужен, начиная с C # 8.0, но код не будет компилироваться в более ранних языковых версиях, если он не предоставлен.
rvnlord
46

Когда вы указываете явный тип переменной диапазона, компилятор вставляет вызов Cast<T>. Итак, это:

bool result = (from Match m in matches
               where m.Groups["name"].Value.Length > 128
               select m).Any();

в точности эквивалентен:

bool result = matches.Cast<Match>()
                     .Where(m => m.Groups["name"].Value.Length > 128)
                     .Any();

который также можно записать как:

bool result = matches.Cast<Match>()
                     .Any(m => m.Groups["name"].Value.Length > 128);

В этом случае Castвызов необходим, потому что MatchCollectionреализует только ICollectionand IEnumerable, а не IEnumerable<T>. Практически все методы расширения LINQ to Objects нацелены на IEnumerable<T>, за заметными исключениями Castи OfType, оба из которых используются для преобразования «слабо» типизированной коллекции (например, MatchCollection) в универсальную, IEnumerable<T>которая затем позволяет выполнять дальнейшие операции LINQ.

Джон Скит
источник
8

Попробуй это:

var matches = myRegEx.Matches(content).Cast<Match>();

Для справки см . Enumerable.Cast:

Преобразует элементы объекта IEnumerableв указанный тип.

По сути, это один из способов превратить файл IEnumerableв IEnumerable<T>.

Эндрю Хэйр
источник
+1 Я пытаюсь понять, почему это было отклонено. Я этого не вижу.
Джейсон 01
@ Джейсон: Скорее всего, кто-то пытался повысить свой ответ.
Эндрю Хэйр
3

Думаю, это будет примерно так:

bool result = matches.Cast<Match>().Any(m => m.Groups["name"].Value.Length > 128);
pstrjds
источник
1
Нет. Все дело в том, что MatchCollectionтолько орудия IEnumerable. Это не строго типизированный.
Джейсон 01
2

Вы можете попробовать что-то вроде этого:

List<Match> matchList = matches.Cast<Match>().Where(m => m.Groups["name"].Value.Length > 128).ToList();
Джеймс Джонсон
источник
-1

РЕДАКТИРОВАТЬ:

 public static IEnumerable<T> AsEnumerable<T>(this IEnumerable enumerable)
 {
      foreach(object item in enumerable)
          yield return (T)item;
 }

Затем вы сможете вызвать этот метод расширения, чтобы превратить его в IEnumerable:

 matches.AsEnumerable<Match>().Any(x => x.Groups["name"].Value.Length > 128);
Tejs
источник
Это лучше, чем у меня, я не помнил, чтобы Any взял предикат.
pstrjds 01
Нет. Все дело в том, что MatchCollectionтолько орудия IEnumerable. Это не строго типизированный.
Джейсон 01
@Jason, за исключением того, что его можно преобразовать в IEnumberable <T> через IEnumberable. Cast <T>
msarchet 01
@msarchet: Да, я знаю, поэтому я поддержал ваш ответ. Этот ответ до редактирования даже не скомпилировался.
Джейсон 01