Usando a sintaxe do método de extensão LINQ em um MatchCollection

91

Eu tenho o seguinte código:

MatchCollection matches = myRegEx.Matches(content);

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

Existe uma maneira de fazer isso usando a sintaxe do método de extensão LINQ?

Algo assim:

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

Respostas:

191
using System.Linq;

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

Você só precisa convertê-lo de um IEnumerablepara um IEnumerable<Match>(IEnumerable <T>) para obter acesso à extensão LINQ fornecida em IEnumerable <T>.

msarchet
fonte
Quem está votando em todas as respostas aqui? Esta resposta obteve minha aprovação, cognrats.
Kevin Kalitowski
1 Estou tentando descobrir por que isso foi rejeitado. Eu não estou vendo isso.
Jason,
Estou realmente confuso sobre como isso foi rejeitado porque é correto
msarchet
Muitas respostas foram rejeitadas. Eu dei uma resposta semelhante, mas espero que seja um pouco mais completa.
Jon Skeet
1
Isso funciona, mas certifique-se de using System.Linqque não haja um erro de sintaxe
Ash Berlin-Taylor,
46

Quando você especifica um tipo de variável de intervalo explícito , o compilador insere uma chamada para Cast<T>. Então, é isso:

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

é exatamente equivalente a:

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

que também pode ser escrito como:

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

Neste caso, a Castchamada é necessária porque MatchCollectionapenas implementa ICollectione IEnumerable, não IEnumerable<T>. Quase todos os métodos de extensão LINQ to Objects são direcionados IEnumerable<T>, com as notáveis ​​exceções de Caste OfType, ambos os quais são usados ​​para converter uma coleção de tipos "fracos" (como MatchCollection) em um genérico IEnumerable<T>- que então permite outras operações LINQ.

Jon Skeet
fonte
7

Experimente isto:

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

Para referência, consulte Enumerable.Cast:

Converte os elementos de um IEnumerableno tipo especificado.

Basicamente, é uma maneira de transformar um IEnumerableem um IEnumerable<T>.

Andrew Hare
fonte
1 Estou tentando descobrir por que isso foi rejeitado. Eu não estou vendo isso.
Jason,
@ Jason: Provavelmente alguém estava tentando impulsionar sua resposta.
Andrew Hare
2

Acho que seria algo assim:

bool result = matches.Cast<Match>().Any(m => m.Groups["name"].Value.Length > 128);
pstrjds
fonte
1
Não. A questão toda é que MatchCollectionapenas implementa IEnumerable. Não é fortemente tipado.
Jason,
2

Você pode tentar algo assim:

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

EDITAR:

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

Então você deve ser capaz de chamar este método de extensão para transformá-lo em um IEnumerable:

 matches.AsEnumerable<Match>().Any(x => x.Groups["name"].Value.Length > 128);
Tejs
fonte
Isso é melhor que o meu, não me lembrava que Any pegou um predicado.
pstrjds 01 de
Não. A questão toda é que MatchCollectionapenas implementa IEnumerable. Não é fortemente tipado.
Jason,
@Jason, exceto que pode ser convertido em um IEnumberable <T> via IEnumberable.Cast <T>
msarchet 01 de
@msarchet: Sim, eu sei, por isso votei contra sua resposta. Essa resposta, antes da edição, nem teria compilado.
Jason,