Verwenden der Syntax der LINQ-Erweiterungsmethode für eine MatchCollection

91

Ich habe folgenden Code:

MatchCollection matches = myRegEx.Matches(content);

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

Gibt es eine Möglichkeit, dies mithilfe der Syntax der LINQ-Erweiterungsmethode zu tun?

Etwas wie das:

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

Antworten:

190
using System.Linq;

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

Sie müssen es nur von einem IEnumerablein einen IEnumerable<Match>(IEnumerable <T>) konvertieren , um Zugriff auf die auf IEnumerable <T> bereitgestellte LINQ-Erweiterung zu erhalten.

msarchet
quelle
Wer stimmt hier nicht über jede Antwort ab? Diese Antwort wird positiv bewertet, Cognrats.
Kevin Kalitowski
+1 Ich versuche herauszufinden, warum dies abgelehnt wurde. Ich sehe es nicht.
Jason
Ich bin wirklich verwirrt darüber, wie dies
abgelehnt wurde,
Viele Antworten wurden abgelehnt. Ich habe eine ähnliche Antwort gegeben, aber eine, von der ich hoffe, dass sie etwas voller ist.
Jon Skeet
1
Dies funktioniert, stellen Sie nur sicher, dass Sie using System.Linqein Syntaxfehler sind
Ash Berlin-Taylor
46

Wenn Sie einen expliziten Bereichsvariablentyp angeben , fügt der Compiler einen Aufruf an ein Cast<T>. Also das:

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

ist genau gleichbedeutend mit:

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

was auch geschrieben werden kann als:

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

In diesem Fall ist der CastAufruf erforderlich, da MatchCollectionnur ICollectionund IEnumerablenicht implementiert wird IEnumerable<T>. Fast alle LINQ to Objects-Erweiterungsmethoden zielen darauf ab IEnumerable<T>, mit den bemerkenswerten Ausnahmen von Castund OfType, die beide verwendet werden, um eine "schwach" typisierte Sammlung (z. B. MatchCollection) in eine generische umzuwandeln IEnumerable<T>- was dann weitere LINQ-Operationen ermöglicht.

Jon Skeet
quelle
1
Auf MSDN: Enumerable.Cast <TResult>
-Methode
7

Versuche dies:

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

Als Referenz siehe Enumerable.Cast:

Konvertiert die Elemente von IEnumerablein den angegebenen Typ.

Im Grunde ist es eine Möglichkeit, aus einem IEnumerableein zu machen IEnumerable<T>.

Andrew Hare
quelle
+1 Ich versuche herauszufinden, warum dies abgelehnt wurde. Ich sehe es nicht.
Jason
@ Jason: Höchstwahrscheinlich hat jemand versucht, seine Antwort zu verbessern.
Andrew Hare
2

Ich denke, es wäre ungefähr so:

bool result = matches.Cast<Match>().Any(m => m.Groups["name"].Value.Length > 128);
pstrjds
quelle
1
Nein, der springende Punkt ist, dass MatchCollectionnur implementiert IEnumerable. Es ist nicht stark typisiert.
Jason
2

Sie können so etwas ausprobieren:

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

BEARBEITEN:

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

Dann sollten Sie diese Erweiterungsmethode aufrufen können, um sie in eine IEnumerable umzuwandeln:

 matches.AsEnumerable<Match>().Any(x => x.Groups["name"].Value.Length > 128);
Tejs
quelle
Das ist besser als meins, ich habe mich nicht daran erinnert, dass Any ein Prädikat genommen hat.
pstrjds
Nein, der springende Punkt ist, dass MatchCollectionnur implementiert IEnumerable. Es ist nicht stark typisiert.
Jason
@ Jason mit der Ausnahme, dass es über IEnumberable in eine IEnumberable <T> umgewandelt werden kann. Cast <T>
msarchet
@msarchet: Ja, ich weiß, deshalb habe ich deine Antwort positiv bewertet. Diese Antwort hätte vor der Bearbeitung nicht einmal kompiliert.
Jason