Menggunakan sintaks metode ekstensi LINQ pada MatchCollection


92

Saya memiliki kode berikut:

MatchCollection matches = myRegEx.Matches(content);

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

Apakah ada cara untuk melakukan ini menggunakan sintaks metode ekstensi LINQ?

Sesuatu seperti ini:

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

Jawaban:


196
using System.Linq;

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

Anda hanya perlu mengonversinya dari sebuah IEnumerableke IEnumerable<Match>(IEnumerable <T>) untuk mendapatkan akses ke ekstensi LINQ yang disediakan di IEnumerable <T>.


Siapa yang memberikan suara untuk setiap jawaban di sini? Jawaban ini mendapat suara positif saya, para cognrat.
Kevin Kalitowski

+1 Saya mencoba mencari tahu mengapa ini tidak disukai. Saya tidak melihatnya.
jason

Saya benar-benar bingung bagaimana ini diturunkan sebagai yang benar
msarchet

1
Ini berfungsi, pastikan Anda melakukannya dengan cara using System.Linqlain itu akan memberikan kesalahan sintaksis
Ash Berlin-Taylor

1
Terima kasih, kepada siapa pun yang bingung, Casttidak diperlukan sejak C # 8.0, tetapi kode tidak dapat dikompilasi dalam versi bahasa sebelumnya jika tidak tersedia.
rvnlord

46

Saat Anda menentukan tipe variabel rentang eksplisit , kompilator menyisipkan panggilan ke Cast<T>. Jadi ini:

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

persis sama dengan:

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

yang juga bisa ditulis sebagai:

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

Dalam hal ini Castpanggilan diperlukan karena MatchCollectionhanya mengimplementasikan ICollectiondan IEnumerable, tidak IEnumerable<T>. Hampir semua metode ekstensi LINQ ke Objek ditargetkan IEnumerable<T>, dengan pengecualian penting dari Castdan OfType, keduanya digunakan untuk mengubah kumpulan yang diketik "lemah" (seperti MatchCollection) menjadi generik IEnumerable<T>- yang kemudian memungkinkan untuk operasi LINQ lebih lanjut.



8

Coba ini:

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

Untuk referensi, silakan lihat Enumerable.Cast:

Mengonversi elemen dari menjadi IEnumerabletipe yang ditentukan.

Pada dasarnya, ini adalah salah satu cara untuk mengubah file IEnumerablemenjadi IEnumerable<T>.


+1 Saya mencoba mencari tahu mengapa ini tidak disukai. Saya tidak melihatnya.
jason

@Jason: Kemungkinan besar seseorang mencoba meningkatkan jawaban mereka.
Andrew Hare

3

Saya pikir itu akan menjadi seperti ini:

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

1
Tidak. Intinya adalah MatchCollectionhanya mengimplementasikan IEnumerable. Ini tidak diketik dengan kuat.
jason

2

Anda dapat mencoba sesuatu seperti ini:

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

-1

EDIT:

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

Maka Anda harus dapat memanggil metode ekstensi ini untuk mengubahnya menjadi IEnumerable:

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

Ini lebih baik dariku, aku tidak ingat Any mengambil predikat.
pstrjds

Tidak. Intinya adalah MatchCollectionhanya mengimplementasikan IEnumerable. Ini tidak diketik dengan kuat.
jason

@Jason kecuali bahwa itu dapat ditransmisikan ke IEnumberable <T> melalui IEnumberable.Cast <T>
msarchet

@msarchet: Ya, saya tahu, itulah sebabnya saya memberi suara positif pada jawaban Anda. Jawaban ini, sebelum diedit, bahkan tidak akan dikompilasi.
jason
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.