Używanie składni metody rozszerzenia LINQ w MatchCollection

92

Mam następujący kod:

MatchCollection matches = myRegEx.Matches(content);

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

Czy istnieje sposób, aby to zrobić przy użyciu składni metody rozszerzenia LINQ?

Coś takiego:

bool result = matches.Any(x => ... );
Tomasz
źródło

Odpowiedzi:

196
using System.Linq;

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

Wystarczy przekonwertować go z an IEnumerablena IEnumerable<Match>(IEnumerable <T>), aby uzyskać dostęp do rozszerzenia LINQ udostępnionego w IEnumerable <T>.

msarchet
źródło
Kto głosuje tutaj na każdą odpowiedź? Ta odpowiedź zbiera moje poparcie, cognrats.
Kevin Kalitowski
+1 Próbuję dowiedzieć się, dlaczego ten głos został odrzucony. Nie widzę tego.
jason
Jestem naprawdę zdezorientowany, jak to się stało w głosowaniu, ponieważ jest poprawne
msarchet
1
To działa, po prostu upewnij się, że jesteś using System.Linqinny, spowoduje to błąd składniowy
Ash Berlin-Taylor
1
Dziękuję wszystkim zdezorientowanym, Castnie jest potrzebny od C # 8.0, ale kod nie zostanie skompilowany we wcześniejszych wersjach językowych, jeśli nie zostanie podany.
rvnlord
46

Po określeniu jawnego typu zmiennej zakresu kompilator wstawia wywołanie Cast<T>. Więc to:

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

jest dokładnie równoważne z:

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

który można również zapisać jako:

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

W tym przypadku Castwywołanie jest wymagane, ponieważ MatchCollectiontylko implementuje, ICollectiona IEnumerablenie IEnumerable<T>. Prawie wszystkie metody rozszerzenia LINQ to Objects są przeznaczone dla IEnumerable<T>, z godnymi uwagi wyjątkami Casti OfType, z których oba są używane do konwertowania kolekcji typu „słabo” (na przykład MatchCollection) na typ ogólny IEnumerable<T>- co następnie umożliwia dalsze operacje LINQ.

Jon Skeet
źródło
1
W witrynie MSDN: metoda Enumerable.Cast <TResult>
DavidRR
8

Spróbuj tego:

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

Aby uzyskać więcej informacji, zobacz Enumerable.Cast:

Konwertuje elementy an IEnumerablena określony typ.

Zasadniczo jest to jeden ze sposobów zmiany pliku IEnumerablew IEnumerable<T>.

Andrew Hare
źródło
+1 Próbuję dowiedzieć się, dlaczego ten głos został odrzucony. Nie widzę tego.
jason
@Jason: Najprawdopodobniej ktoś próbował wzmocnić swoją odpowiedź.
Andrew Hare
3

Myślę, że byłoby to coś takiego:

bool result = matches.Cast<Match>().Any(m => m.Groups["name"].Value.Length > 128);
pstrjds
źródło
1
Nie. Chodzi o to, że MatchCollectiontylko narzędzia IEnumerable. Nie jest napisane silnie.
jason
2

Możesz spróbować czegoś takiego:

List<Match> matchList = matches.Cast<Match>().Where(m => m.Groups["name"].Value.Length > 128).ToList();
James Johnson
źródło
-1

EDYTOWAĆ:

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

Następnie powinieneś móc wywołać tę metodę rozszerzenia, aby przekształcić ją w IEnumerable:

 matches.AsEnumerable<Match>().Any(x => x.Groups["name"].Value.Length > 128);
Tejs
źródło
To jest lepsze niż moje, nie pamiętałem, że Any wziął predykat.
pstrjds
Nie. Chodzi o to, że MatchCollectiontylko narzędzia IEnumerable. Nie jest napisane silnie.
jason
@Jason z wyjątkiem tego, że można go przesłać do IEnumberable <T> za pośrednictwem IEnumberable.Cast <T>
msarchet
@msarchet: Tak, wiem, dlatego zagłosowałem za twoją odpowiedzią. Ta odpowiedź, przed edycją, nawet by się nie skompilowała.
jason