2013-01-05 39 views
5

Tôi đọc C# AsEnumerable:..Tại sao Áp dụng Phương thức AsEnumerable() cho một mảng?

"Giao diện IEnumerable là một giao diện chung Điều này có nghĩa nó định nghĩa một mẫu mà loại có thể thực hiện cho Looping Các AsEnumerable phương pháp , một phương pháp chung chung, cho phép bạn cast một cụ thể loại để tương đương IEnumerable của nó"

tiếp theo, một ví dụ mã:

using System; 
using System.Linq; 

class Program 
{ 
    static void Main() 
    { 
     // Create an array type. 
     int[] array = new int[2]; 
     array[0] = 5; 
     array[1] = 6; 
     // Call AsEnumerable method. 
     var query = array.AsEnumerable(); 
     foreach (var element in query) 
     { 
      Console.WriteLine(element); 
     } 
    } 
} 

Có vẻ như tôi cần chuyển đổi một mảng thành đối tượng loại IEnumerable để sử dụng vòng lặp (foreach?).

Nhưng áp dụng foreach trực tiếp đến một mảng sản lượng chính xác các kết quả tương tự:

using System; 
//using System.Linq; 

class Program 
{ 
    static void Main() 
    { 
     // Create an array type. 
     int[] array = new int[2]; 
     array[0] = 5; 
     array[1] = 6; 
     // Call AsEnumerable method. 
     //var query = array.AsEnumerable(); 
     foreach (var element in array) 
     { 
      Console.WriteLine(element); 
     } 
    } 
} 

Vì vậy, toàn bộ trang web với một lời giải thích của AsEnumerable() phương pháp là khoảng trống cho tôi.
Tôi đã bỏ lỡ điều gì?

+3

+1 ví dụ hoàn toàn ngu ngốc và tác giả của trang web không có đầu mối nào được sử dụng cho 'AsEnumerable'. –

+1

Cảm ơn tất cả những người trả lời sự giúp đỡ và đặc biệt là người bình luận [@Konrad Rudolph] (http://stackoverflow.com/users/1968/konrad-rudolph) vì đã khiến tôi không hiểu nhầm lẫn với một người quan tâm đến cú pháp về cách sử dụng phương thức.Chìa khóa trong câu hỏi là những gì tôi (nhưng không phải là bài báo được trích dẫn, mà tôi hiểu trước khi yêu cầu) bỏ qua. Tôi đã đọc tất cả các câu trả lời vài lần nhưng tôi thực sự thích các hình minh họa mã kèm theo để được chạy thay vì đọc các lý thuyết rất khôn ngoan và chính xác. Có vẻ như câu trả lời chính xác đã bị một downvote vì lợi ích của việc giáo dục tôi. –

Trả lời

4

Ví dụ này là xấu và nó sẽ cảm thấy xấu. Đây là một tốt hơn, nếu ví dụ hơi giả tạo:

Nếu tôi có một phương pháp mở rộng định nghĩa trên, chúng ta hãy nói, kiểu mảng, như thế này:

public static class ArrayExtension { 

    public static bool Any<T>(this T[] source, Func<T,bool> predicate) 
    { 
     Console.WriteLine("Undesirable side behaviour"); 
     SomeResourceIntensiveOperation(); 

     Console.WriteLine("Inefficient implementation"); 
     return source.Where(predicate).Count() != 0; 
    } 

} 

và tôi làm

int[] nums = new []{1,2,3,4,5}; 
nums.Any(n=> n % 2 == 0); 

Nếu sẽ thực hiện và chạy thực hiện của tôi, ngay cả khi tôi không cần điều đó. Bằng cách thực hiện

nums.AsEnumerable().Any(n => n % 2 == 0); 

nó sẽ gọi triển khai mặc định.

Các lợi ích thực sự là khi bạn đang sử dụng IQueryable triển khai (ví dụ LINQ-to-SQL), bởi vì, ví dụ, Where for IEnumerable được định nghĩa là

public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source, 
Func<TSource, bool> predicate) 

nhưng IQueryable.Where được định nghĩa với

public static IQueryable<TSource> Where<TSource>(
this IQueryable<TSource> source, 
Expression<Func<TSource, bool>> predicate) 

Khi hành vi IQueryable không thể truy cập được, người ta có thể gọi số AsEnumerable() để buộc hành vi IEnumerable.

+0

Xin lỗi, đó là ví dụ vô lý nhất mà tôi từng thấy. Quy tắc ví dụ: KISS. Đơn giản nhất có thể. ĐỂ làm cho điểm ONE bạn thực hiện. Bạn có quá nhiều lời giải thích không tốt đẹp đến mức có thể có hoặc thậm chí không được ra ngoài và tham khảo chéo - tôi chỉ hy vọng rằng bạn không bao giờ viết một hướng dẫn lập trình. – TomTom

+5

@TomTom Bạn phải hoàn toàn tắt rocker của mình. Ví dụ này là minh hoạ * hoàn hảo * của những gì 'AsEnumerable' làm. Cụ thể, đó là một ví dụ ** tối thiểu **. Nó không chứa gì ngoài các thành phần tối thiểu để minh họa cho việc sử dụng nó. Tôi đề nghị bạn có thể ngủ một đêm về điều này, sau đó trở lại để nhìn vào nó một lần nữa. –

+0

@TomTom Tôi luôn thích một biến thể trên KISS: "Hãy giữ nó đơn giản nhất có thể, nhưng không đơn giản hơn." :) Và tôi thực sự không nghĩ rằng đưa ra phương pháp mở rộng khi tôi giải thích một phương pháp mở rộng là overcomplicating mọi thứ. – SWeko

1

Không có ý nghĩa gì trong ví dụ của bạn một cách hợp lý (ví dụ: từ mảng). Tôi cho rằng đoạn mã đầu tiên đã được viết bởi một người mới bắt đầu, hoặc - hơn nữa - một ví dụ. Nó có ý nghĩa trong ý nghĩa của LINQ là "AsEnumerable" kích hoạt việc đánh giá truy vấn và tùy thuộc vào ORM Điều đó có nghĩa là giải phóng kết nối cơ sở dữ liệu để tái sử dụng trong vòng lặp.

THƯ SAID:

Bạn đã đọc quá nhiều ví dụ. Trong một ví dụ, mã là không được "tốt" nhưng để hiển thị một điểm. Trong trường hợp này, nó có thể có ý nghĩa để DEMONSTRATE việc sử dụng AsEnumerable - và một mảng là đối tượng đếm được nhanh nhất để khởi tạo (về dòng mã), để giữ cho ví dụ ngắn. Ví dụ chỉ ra những điều cụ thể, chúng không phải là "mã tốt" cho bất cứ điều gì.

+1

Tôi không đồng ý. Như bạn đã nói, "trong một ví dụ, mã là có ... để hiển thị một điểm". Ví dụ trong câu hỏi hoàn toàn không làm điều đó, vì có * không * điểm trong việc áp dụng 'AsEnumerable' vào một mảng. Một ví dụ tốt sẽ cho thấy sự khác biệt giữa việc sử dụng nó và không sử dụng nó trong một truy vấn LINQ to SQL. Bạn đã đọc trang web OP được liên kết đến chưa? Tác giả của nó là hoàn toàn không biết gì. –

+0

Nó thể hiện cách sử dụng từ một quan điểm cú pháp. – TomTom

+1

Làm thế nào là có liên quan hoặc hữu ích? Không ai cần phải nói cách gọi một số phương pháp phổ biến. Họ cũng có thể chứng minh tương tự bằng cách gọi 'foo.Bar()' với các tên được tạo sẵn, không cần phải đề cập đến 'System.Array' và' AsEnumerable'. Ví dụ này không hiển thị nhiều hơn thế. –

2

Từ MSDN

Phương pháp AsEnumerable<TSource> (IEnumerable<TSource>) không có tác dụng nào khác ngoài việc thay đổi kiểu thời gian biên dịch nguồn từ một loại mà thực hiện IEnumerable<T>-IEnumerable<T> riêng của mình.

AsEnumerable<TSource> (IEnumerable<TSource>) có thể được sử dụng để chọn giữa triển khai truy vấn khi chuỗi triển khai IEnumerable<T> nhưng cũng có sẵn một bộ phương pháp truy vấn công khai khác. Ví dụ, cho một lớp chung Bảng thực hiện IEnumerable<T> và có các phương thức riêng của nó như Where, SelectSelectMany, một cuộc gọi đến Where sẽ gọi phương thức Bảng công khai Where. Một kiểu bảng biểu diễn một bảng cơ sở dữ liệu có thể có một phương thức Where lấy đối số vị từ như một cây biểu thức và chuyển đổi cây thành SQL để thực thi từ xa. Nếu thực thi từ xa không được mong muốn, ví dụ vì biến vị ngữ gọi phương thức cục bộ, phương thức AsEnumerable<TSource> có thể được sử dụng để ẩn các phương thức tùy chỉnh và thay vào đó làm cho toán tử truy vấn chuẩn có sẵn.

0

Đây chỉ là một ví dụ khác. Giả sử tôi có phương pháp này:

static void MyMeth(int[] numbers) 
{ 
    var query = numbers.Reverse(); // works fine, calls Linq extension 

    // ... use query ... 
} 

Sau đó, tôi quyết định thay đổi numbers thành một List<int> thay vào đó, và cố gắng:

static void MyMeth(List<int> numbers) 
{ 
    var query = numbers.Reverse(); // will not compile! 

    // ... use query ... 
} 

Vấn đề ở đây là lớp List<>một phương pháp đó cũng là được gọi là Reverse. Phương thức đó trả về void (vì nó sửa đổi List<> gốc tại chỗ). Tôi không muốn điều đó. Một giải pháp sẽ được upCast numbers một cách rõ ràng:

static void MyMeth(List<int> numbers) 
{ 
    var query = ((IEnumerable<int>)numbers).Reverse(); // fine; Linq 

    // ... use query ... 
} 

Nhưng giải pháp khác sẽ AsEnumerable<>, vì vậy:

static void MyMeth(List<int> numbers) 
{ 
    var query = numbers.AsEnumerable().Reverse(); // fine too; Linq 

    // ... use query ... 
} 

Kết luận: Mục đích của AsEnumerable phương pháp là "quên" các phương pháp trên chuyên loại xảy ra để "ẩn" các phương thức mở rộng theo loại chung IEnumerable<>. Điều này có thể cực kỳ quan trọng trong trường hợp loại "chuyên" là/kế thừa IQueryable<>, nơi có các phương pháp (mở rộng) Where, Select và cứ làm điều gì đó khác (cụ thể là nhập lambda làm cây biểu thức, phân tích và " dịch "nó thành SQL hoặc một cái gì đó) hơn làm Where, Select, v.v. trên IEnumerable<>.

Các vấn đề liên quan