การใช้ไวยากรณ์วิธีการขยาย LINQ บน MatchCollection


92

ฉันมีรหัสต่อไปนี้:

MatchCollection matches = myRegEx.Matches(content);

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

มีวิธีดำเนินการโดยใช้ไวยากรณ์วิธีการขยาย LINQ หรือไม่?

สิ่งนี้:

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

คำตอบ:


196
using System.Linq;

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

คุณเพียงแค่ต้องแปลงจาก an IEnumerableเป็นIEnumerable<Match>(IEnumerable <T>) เพื่อเข้าถึงส่วนขยาย LINQ ที่มีให้บน IEnumerable <T>


ใครโหวตทุกคำตอบที่นี่ คำตอบนี้ทำให้ฉันได้รับคะแนนโหวตเพิ่มขึ้น
Kevin Kalitowski

+1 ฉันกำลังพยายามหาสาเหตุว่าทำไมจึงถูกลดคะแนน ฉันไม่เห็นมัน
สัน

ฉันสับสนจริงๆว่ามันลงคะแนนได้อย่างไรว่ามันถูกต้อง
msarchet

1
ใช้งานได้เพียงตรวจสอบให้แน่ใจว่าคุณเป็นusing System.Linqคนอื่นมันจะให้ข้อผิดพลาดทางไวยากรณ์
Ash Berlin-Taylor

1
ขอบคุณสำหรับทุกคนที่สับสนCastไม่จำเป็นต้องใช้ตั้งแต่ C # 8.0 แต่รหัสจะไม่รวบรวมในเวอร์ชันภาษาก่อนหน้าหากไม่มีให้
rvnlord

46

เมื่อคุณระบุอย่างชัดเจนCast<T>ชนิดตัวแปรช่วงคอมไพเลอร์แทรกเรียกไปยัง ดังนั้นสิ่งนี้:

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

เทียบเท่ากับ:

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

ซึ่งสามารถเขียนเป็น:

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

ในกรณีนี้Castโทรถูกต้องเนื่องจากMatchCollectionการดำเนินการเท่านั้นICollectionและไม่IEnumerable IEnumerable<T>วิธีการขยาย LINQ to Objects เกือบทั้งหมดกำหนดเป้าหมายไว้ที่IEnumerable<T>ข้อยกเว้นที่น่าสังเกตของCastและOfTypeทั้งสองอย่างนี้ใช้ในการแปลงคอลเล็กชันที่พิมพ์ "อ่อนแอ" (เช่นMatchCollection) เป็นแบบทั่วไปIEnumerable<T>ซึ่งจะช่วยให้สามารถดำเนินการ LINQ เพิ่มเติมได้



8

ลองสิ่งนี้:

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

สำหรับการอ้างอิงโปรดดูEnumerable.Cast:

แปลงองค์ประกอบของ an เป็นIEnumerableชนิดที่ระบุ

โดยทั่วไปแล้วมันเป็นวิธีหนึ่งในการเปลี่ยนIEnumerableเป็นIEnumerable<T>ไฟล์.


+1 ฉันกำลังพยายามหาสาเหตุว่าทำไมจึงถูกลดคะแนน ฉันไม่เห็นมัน
สัน

@ เจสัน: มีคนส่วนใหญ่พยายามเพิ่มคำตอบ
Andrew Hare

3

ฉันคิดว่ามันจะเป็นแบบนี้:

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

1
ฉบับที่จุดรวมก็คือว่าการดำเนินการเท่านั้นMatchCollection IEnumerableไม่ได้พิมพ์อย่างรุนแรง
สัน


-1

แก้ไข:

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

จากนั้นคุณควรจะสามารถเรียกวิธีการขยายนี้เพื่อเปลี่ยนเป็น IEnumerable:

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

นี่ดีกว่าของฉันฉันจำไม่ได้ว่า Any ใช้เพรดิเคต
pstrjds

ฉบับที่จุดรวมก็คือว่าการดำเนินการเท่านั้นMatchCollection IEnumerableไม่ได้พิมพ์อย่างรุนแรง
สัน

@Jason ยกเว้นว่า Castable ไปยัง IEnumberable <T> ผ่าน IEnumberable แคสต์ <T>
msarchet

@msarchet: ใช่ฉันรู้นี่คือเหตุผลที่ฉันโหวตคำตอบของคุณ คำตอบนี้ก่อนการแก้ไขจะไม่ได้รวบรวมด้วยซ้ำ
สัน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.