Các Select
và Where
phương pháp có sẵn trong Linq. Mọi nhà phát triển nên biết gì về hai phương pháp này? Ví dụ: khi nào sử dụng cái này hơn cái kia, bất kỳ lợi thế nào của việc sử dụng cái này hơn cái kia, v.v.
Các Select
và Where
phương pháp có sẵn trong Linq. Mọi nhà phát triển nên biết gì về hai phương pháp này? Ví dụ: khi nào sử dụng cái này hơn cái kia, bất kỳ lợi thế nào của việc sử dụng cái này hơn cái kia, v.v.
Câu trả lời:
Ở đâu
tìm các mục phù hợp và chỉ trả về những mục phù hợp ( lọc ).
-> IEnumerable<A>
vào, IEnumerable<A>
ra
Lựa chọn
trả về một cái gì đó cho tất cả các mục trong nguồn ( phép chiếu / chuyển đổi ). Cái gì đó có thể là chính các mục, nhưng thường là một phép chiếu của một số loại.
-> IEnumerable<A>
vào, IEnumerable<B>
ra
Select
sẽ luôn trả về cùng một số phần tử trong danh sách (bất kể bạn có thể có điều kiện lọc nào). Where
có thể trả về ít phần tử hơn tùy thuộc vào điều kiện bộ lọc của bạn.
Where == filter
vàSelect == map
Select và Where là hai toán tử hoàn toàn khác nhau hoạt động trên IEnumerable s.
Cái đầu tiên chúng ta gọi là Toán tử chiếu , còn cái cuối cùng là Toán tử hạn chế .
Một cách thú vị để có cái nhìn sâu sắc về hành vi của các toán tử như vậy là xem xét "loại chức năng" của họ.
Chọn: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; nó nhận cả đầu vào là IEnumerable chứa các phần tử kiểu T1 và một hàm biến đổi các phần tử kiểu T1 thành các phần tử kiểu T2. Đầu ra là IEnumerable chứa các phần tử kiểu T2.
Từ đó, người ta có thể dễ dàng đoán rằng toán tử này sẽ tạo ra đầu ra của nó bằng cách áp dụng hàm đầu vào trên từng phần tử của IEnumerable đầu vào, và gói kết quả bên trong IEnumerable mới.
Sử dụng một số ký hiệu giống như toán học, nó nhận làm đầu vào (a, b, c, ...): IEnumerable <T1> và f: T1 → T2 và tạo ra (f (a), f (b), f (c) , ...): IEnumerable <T2>
Trong đó: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; cái này lấy IEnumerable chứa các phần tử của kiểu T1 và một vị từ trên T1 (nghĩa là một hàm tạo ra kết quả boolean cho đầu vào kiểu T1). Bạn thấy rằng đầu ra cũng là một IEnumerable chứa các phần tử của kiểu T1.
Lần này, người ta sẽ đoán rằng một phần tử của IEnumerable đầu vào sẽ có mặt trên IEnumerable đầu ra tùy thuộc vào kết quả của việc áp dụng vị từ cho phần tử. Thêm vào đó ngữ nghĩa của tên toán tử, bạn có thể chắc chắn rằng nó sẽ tạo ra đầu ra IEnumerable bằng cách lấy từ đầu vào một chỉ những phần tử đánh giá là true trên ứng dụng của vị từ.
Những người có nền tảng lập trình chức năng thường nghĩ như thế này. Nó cho phép bạn suy luận (hoặc ít nhất là đoán ...) những gì một toán tử làm chỉ bằng cách nhìn vào kiểu của nó!
Như một bài tập, hãy thử xem các toán tử khác được LINQ giới thiệu trên IEnumerables và suy ra hành vi của chúng, trước khi xem tài liệu!
Chúng khác nhau:
Select
là tất cả về sự biến đổi .
Where
là tất cả về lọc .
Where
~ = Bộ lọc
Select
~ = Bản đồ
Cả hai đều trở lại IEnumerable<T>
Nếu bạn biết họ đã triển khai các phương pháp mở rộng ở đâu và chọn lọc như thế nào, bạn có thể dự đoán nó đang làm gì ... Tôi đã cố gắng triển khai ở đâu và chọn các phương pháp mở rộng ... Bạn có thể xem qua ...
Nơi thực hiện ::
public static IEnumerable<Tsource> Where<Tsource> ( this IEnumerable<Tsource> a , Func<Tsource , bool> Method )
{
foreach ( var data in a )
{
//If the lambda Expression(delegate) returns "true" Then return the Data. (use 'yield' for deferred return)
if ( Method.Invoke ( data ) )
{
yield return data;
}
}
}
Chọn triển khai ::
public static IEnumerable<TResult> Select<TSource , TResult> ( this IEnumerable<TSource> a , Func<TSource , TResult> Method )
{
foreach ( var item in a )
{
//Each iteration call the delegate and return the Data back.(use 'yield' for deferred return)
yield return Method.Invoke ( item );
}
}
Việc triển khai của tôi hoạt động tốt cho bất kỳ bộ sưu tập nào ... Nhưng nó khác với các phương pháp Mở rộng đã triển khai của Microsoft, Bởi vì chúng sử dụng cây biểu thức để triển khai giống nhau.
Trong trường hợp Chọn nó, bạn có thể ánh xạ tới IEnumerable của một cấu trúc mới.
A.Select(x=>new X{UID=x.uid, UNAME=x.uname})
//input as [IEnumerable<A>] --------> return output as [IEnumerable<X> ]
Where () hoạt động như một bộ lọc đối với IEnumerable, nó sẽ trả về kết quả dựa trên mệnh đề where.
A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] --------> return output as [IEnumerable<A> ]