Використання синтаксису методу розширення 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 => ... );

Відповіді:


192
using System.Linq;

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

Вам просто потрібно перетворити його з IEnumerableна IEnumerable<Match>(IEnumerable <T>), щоб отримати доступ до розширення LINQ, яке надається на IEnumerable <T>.


Хто тут голосує за кожну відповідь? Ця відповідь отримує мій прихильник, когнират.
Kevin Kalitowski

+1 Я намагаюся зрозуміти, чому це було проти. Я цього не бачу.
jason

Мене дуже бентежить, як за це проголосували, як правильно
msarchet

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лише реалізує ICollectionта IEnumerable, а не IEnumerable<T>. Практично всі методи розширення LINQ to Objects орієнтовані IEnumerable<T>, за винятком винятків Castі OfType, обидва з яких використовуються для перетворення "слабо" набраної колекції (наприклад, MatchCollection) у загальну, IEnumerable<T>що надалі дозволяє проводити подальші операції LINQ.



8

Спробуйте це:

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

Для довідки див Enumerable.Cast.

Перетворює елементи an IEnumerableу вказаний тип.

В основному це один із способів перетворення " IEnumerableна" IEnumerable<T>.


+1 Я намагаюся зрозуміти, чому це було проти. Я цього не бачу.
jason

@ Джейсон: Швидше за все хтось намагався підсилити свою відповідь.
Andrew Hare

3

Я думаю, це було б приблизно так:

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

1
Ні. Вся справа в тому, що MatchCollectionтільки реалізує IEnumerable. Він не набраний сильно.
jason

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);

Це краще мого, я не пам’ятав, що Будь-який взяв предикат.
pstrjds

Ні. Вся справа в тому, що MatchCollectionтільки реалізує IEnumerable. Він не сильно набраний.
jason

@Jason, за винятком того, що його можна перекласти на IEnumberable <T> через IEnumberable.Cast <T>
msarchet

@msarchet: Так, я знаю, саме тому я підтримав вашу відповідь. Цю відповідь до редагування навіть не склали.
jason
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.