Sử dụng cú pháp phương thức mở rộng LINQ trên MatchCollection


92

Tôi có mã sau:

MatchCollection matches = myRegEx.Matches(content);

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

Có cách nào để thực hiện việc này bằng cách sử dụng cú pháp phương thức mở rộng LINQ không?

Một cái gì đó như thế này:

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

Câu trả lời:


192
using System.Linq;

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

Bạn chỉ cần chuyển đổi nó từ một IEnumerablethành một IEnumerable<Match>(IEnumerable <T>) để có quyền truy cập vào phần mở rộng LINQ được cung cấp trên IEnumerable <T>.


Ai là người bỏ phiếu cho mọi câu trả lời ở đây? Câu trả lời này nhận được sự ủng hộ của tôi, chúc mừng.
Kevin Kalitowski

+1 Tôi đang cố gắng tìm hiểu lý do tại sao điều này bị phản đối. Tôi không nhìn thấy nó.
jason

Tôi thật sự bối rối như thế nào xuống nhận này được bình chọn là nó là đúng
msarchet

1
Công trình này, chỉ cần đảm bảo rằng bạn đang using System.Linqkhác nó sẽ cho một lỗi cú pháp
Ash Berlin-Taylor

1
Cảm ơn bạn, đối với bất kỳ ai nhầm lẫn, Castkhông cần thiết vì C # 8.0, nhưng mã sẽ không được biên dịch trong các phiên bản ngôn ngữ trước đó nếu nó không được cung cấp.
rvnlord

46

Khi bạn chỉ định một loại biến phạm vi rõ ràng , trình biên dịch sẽ chèn một lệnh gọi tới Cast<T>. Vì vậy, điều này:

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

chính xác tương đương với:

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

cũng có thể được viết là:

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

Trong trường hợp này, Castlệnh gọi là bắt buộc vì MatchCollectionchỉ thực hiện ICollectionIEnumerablekhông IEnumerable<T>. Hầu hết tất cả các phương thức mở rộng LINQ to Object đều được nhắm mục tiêu IEnumerable<T>, với các ngoại lệ đáng chú ý là CastOfType, cả hai đều được sử dụng để chuyển đổi một tập hợp được đánh máy "yếu" (chẳng hạn như MatchCollection) thành một tập hợp chung IEnumerable<T>- sau đó cho phép các hoạt động LINQ tiếp theo.



8

Thử cái này:

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

Để tham khảo, vui lòng xem Enumerable.Cast:

Chuyển đổi các phần tử của an IEnumerablethành kiểu được chỉ định.

Về cơ bản, đó là một cách để biến một IEnumerablethành một IEnumerable<T>.


+1 Tôi đang cố gắng tìm hiểu lý do tại sao điều này bị phản đối. Tôi không nhìn thấy nó.
jason

@Jason: Nhiều khả năng ai đó đang cố gắng tăng câu trả lời của họ.
Andrew Hare

3

Tôi nghĩ nó sẽ như thế này:

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

1
Không. Toàn bộ vấn đề là MatchCollectionchỉ thực hiện IEnumerable. Nó không được đánh máy mạnh.
jason

2

Bạn có thể thử một cái gì đó như sau:

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

-1

BIÊN TẬP:

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

Sau đó, bạn sẽ có thể gọi phương thức mở rộng này để biến nó thành IEnumerable:

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

Cái này tốt hơn cái này của tôi, tôi không nhớ rằng Any lấy một vị ngữ.
pstrjds

Không. Toàn bộ vấn đề là MatchCollectionchỉ thực hiện IEnumerable. Nó không được đánh máy mạnh.
jason

@ Jason ngoại trừ việc nó là bột nhôm để một IEnumberable <T> qua IEnumberable.Cast <T>
msarchet

@msarchet: Vâng, tôi biết, đó là lý do tại sao tôi ủng hộ câu trả lời của bạn. Câu trả lời này, trước khi chỉnh sửa, thậm chí sẽ không được biên dịch.
jason
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.