Utilisation de la syntaxe de la méthode d'extension LINQ sur un MatchCollection

92

J'ai le code suivant:

MatchCollection matches = myRegEx.Matches(content);

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

Existe-t-il un moyen de le faire en utilisant la syntaxe de la méthode d'extension LINQ?

Quelque chose comme ça:

bool result = matches.Any(x => ... );
Thomas
la source

Réponses:

192
using System.Linq;

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

Il vous suffit de le convertir de un IEnumerableen un IEnumerable<Match>(IEnumerable <T>) pour accéder à l'extension LINQ fournie sur IEnumerable <T>.

msarchet
la source
Qui vote toutes les réponses ici? Cette réponse me plaît, cognrats.
Kevin Kalitowski le
+1 J'essaie de comprendre pourquoi ce vote a été rejeté. Je ne le vois pas.
jason le
Je suis vraiment confus quant à la façon dont cela a été voté car il est correct
msarchet
1
Cela fonctionne, assurez-vous simplement que vous êtes using System.Linqsinon, cela donnera une erreur de syntaxe
Ash Berlin-Taylor
1
Merci, à tous ceux qui sont confus, ce Castn'est pas nécessaire depuis C # 8.0, mais le code ne sera pas compilé dans les versions linguistiques antérieures s'il n'est pas fourni.
rvnlord
46

Lorsque vous spécifiez un type de variable de plage explicite , le compilateur insère un appel à Cast<T>. Donc ça:

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

équivaut exactement à:

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

qui peut aussi s'écrire:

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

Dans ce cas, l' Castappel est requis car MatchCollectionimplémente uniquement ICollectionet IEnumerable, pas IEnumerable<T>. Presque toutes les méthodes d'extension LINQ to Objects sont ciblées IEnumerable<T>, à l'exception notable de Castet OfType, qui sont tous deux utilisés pour convertir une collection typée "faiblement" (telle que MatchCollection) en un générique IEnumerable<T>- qui permet ensuite d'autres opérations LINQ.

Jon Skeet
la source
8

Essaye ça:

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

Pour référence, veuillez consulter Enumerable.Cast:

Convertit les éléments d'un IEnumerabledans le type spécifié.

Fondamentalement, c'est une façon de transformer un IEnumerablefichier IEnumerable<T>.

Andrew Hare
la source
+1 J'essaie de comprendre pourquoi ce vote a été rejeté. Je ne le vois pas.
jason le
@Jason: Très probablement, quelqu'un essayait de renforcer sa réponse.
Andrew Hare
3

Je pense que ce serait quelque chose comme ça:

bool result = matches.Cast<Match>().Any(m => m.Groups["name"].Value.Length > 128);
pstrjds
la source
1
Non. Le fait est que MatchCollectionseuls les outils IEnumerable. Il n'est pas fortement typé.
jason le
2

Vous pouvez essayer quelque chose comme ceci:

List<Match> matchList = matches.Cast<Match>().Where(m => m.Groups["name"].Value.Length > 128).ToList();
James Johnson
la source
-1

ÉDITER:

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

Ensuite, vous devriez pouvoir appeler cette méthode d'extension pour la transformer en un IEnumerable:

 matches.AsEnumerable<Match>().Any(x => x.Groups["name"].Value.Length > 128);
Tejs
la source
C'est mieux que le mien, je ne me souvenais pas qu'Any prenait un prédicat.
pstrjds
Non. Le fait est que MatchCollectionseuls les outils IEnumerable. Il n'est pas fortement typé.
jason le
@Jason sauf qu'il peut être converti en un IEnumberable <T> via IEnumberable.Cast <T>
msarchet
@msarchet: Oui, je sais, c'est pourquoi j'ai voté pour votre réponse. Cette réponse, avant la modification, n'aurait même pas été compilée.
jason le