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

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


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.



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


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

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

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.