Usando la sintaxis del método de extensión LINQ en una MatchCollection

92

Tengo el siguiente código:

MatchCollection matches = myRegEx.Matches(content);

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

¿Hay alguna forma de hacer esto usando la sintaxis del método de extensión LINQ?

Algo como esto:

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

Respuestas:

192
using System.Linq;

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

Solo necesita convertirlo de an IEnumerablea IEnumerable<Match>(IEnumerable <T>) para obtener acceso a la extensión LINQ proporcionada en IEnumerable <T>.

msarchet
fuente
¿Quién está votando cada respuesta aquí? Esta respuesta recibe mi voto a favor, cognrats.
Kevin Kalitowski
+1 Estoy tratando de averiguar por qué se votó en contra. No lo estoy viendo.
jason
Estoy realmente confundido en cuanto a cómo se votó esto, ya que es correcto
msarchet
1
Esto funciona, solo asegúrese de estar de lo using System.Linqcontrario, dará un error de sintaxis
Ash Berlin-Taylor
1
Gracias, a cualquiera que esté confundido, Castno es necesario desde C # 8.0, pero el código no se compilará en versiones de idiomas anteriores si no se proporciona.
rvnlord
46

Cuando especifica un tipo de variable de rango explícito , el compilador inserta una llamada a Cast<T>. Así que esto:

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

es exactamente equivalente a:

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

que también se puede escribir como:

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

En este caso la Castllamada es necesaria porque MatchCollectionsolo implementa ICollectiony IEnumerable, no IEnumerable<T>. Casi todos los métodos de extensión de LINQ to Objects están dirigidos a IEnumerable<T>, con las notables excepciones de Casty OfType, los cuales se utilizan para convertir una colección de tipo "débil" (como MatchCollection) en una genérica IEnumerable<T>, lo que permite realizar más operaciones LINQ.

Jon Skeet
fuente
8

Prueba esto:

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

Para referencia, consulte Enumerable.Cast:

Convierte los elementos de an IEnumerableal tipo especificado.

Básicamente es una forma de convertir un archivo IEnumerableen un IEnumerable<T>.

Andrew Hare
fuente
+1 Estoy tratando de averiguar por qué se votó en contra. No lo estoy viendo.
jason
@Jason: Lo más probable es que alguien estuviera tratando de mejorar su respuesta.
Andrew Hare
3

Creo que sería algo como esto:

bool result = matches.Cast<Match>().Any(m => m.Groups["name"].Value.Length > 128);
pstrjds
fuente
1
No. El punto es que MatchCollectionsolo se implementa IEnumerable. No está fuertemente tipado.
Jason
2

Puedes probar algo como esto:

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

EDITAR:

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

Entonces debería poder llamar a este método de extensión para convertirlo en un IEnumerable:

 matches.AsEnumerable<Match>().Any(x => x.Groups["name"].Value.Length > 128);
Tejs
fuente
Esto es mejor que el mío, no recordaba que Any tomara un predicado.
pstrjds
No. El punto es que MatchCollectionsolo se implementa IEnumerable. No está fuertemente tipado.
Jason
@Jason, excepto que es Castable a un IEnumberable <T> a través de IEnumberable.Cast <T>
msarchet
@msarchet: Sí, lo sé, por eso voté a favor de tu respuesta. Esta respuesta, antes de la edición, ni siquiera se habría compilado.
jason