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

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>.


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.



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>.


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

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

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

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.