2011-10-20 18 views
6

Tôi biết IEnumerable đã được thảo luận nhiều lần ở đây nhưng tôi không thể tìm thấy câu trả lời cho câu hỏi cụ thể của tôi vì vậy tôi đưa nó lên như một câu hỏi mới.Nhiều điều tra của IEnumerable

Hãy xem xét các đoạn mã sau:

static void Main(string[] args) 
    { 

     List<string> testList = new List<string> {"Test", "Test1", "Test1"}; 
     IEnumerable<string> filtered = testList.Where(x => x == "Test1"); 

     DoSomeWork(filtered); 
     DoSomeMoreWork(filtered); 
    } 

    public static void DoSomeWork(IEnumerable<string> items) 
    { 
     foreach (var item in items) 
     { 
      Console.WriteLine("do some work"); 
     } 
    } 

    public static void DoSomeMoreWork(IEnumerable<string> items) 
    { 
     foreach (var item in items) 
     { 
      Console.WriteLine("do some more work"); 
     } 
    } 

Tôi có phải không, mà điều này gây ra không chỉ có hai mục trong "lọc" để lặp hai lần nhưng thực sự các mục trong "testList"? Vì vậy, xem xét rằng "testList" là một danh sách lớn với 10000 mục và "lọc" làm giảm nó thành 10 mục, nó sẽ thông minh hơn để làm cho "lọc" một danh sách (aka var sử dụng và chỉ cần thêm ToList() ở cuối)

EDIT: Đó là câu hỏi đáng xấu hổ nhất mà tôi từng hỏi ở đây. Tôi biết nó sẽ là xấu để lặp lại một IQueryable ví dụ bởi vì điều này sẽ dẫn đến việc lấy dữ liệu hai lần từ DB. Tuy nhiên tôi đã không chắc chắn chính xác về trong danh sách bộ nhớ. Tôi sẽ xóa các câu hỏi nếu tôi có thể ;-)

Trả lời

0

Danh sách được ultimatly kế thừa từ IEnumrable kiểm tra

public class List<T> : IList<T>, ICollection<T>, 
    IEnumerable<T>, IList, ICollection, IEnumerable 

Một điều này nhiều hơn bạn có thể tạo danh sách các IEnurable sử dụng constructor sau avaialble

public List(
    IEnumerable<T> collection 
) 

EDIT

Danh sách lọc đã được nhận lại được lặp lại hai lần bởi cả hai phương pháp nhưng appe phương thức nd .ToList() ở cuối.

IEnumerable<string> filtered = testList.Where(x => x == "Test1").ToList(); 

http://msdn.microsoft.com/en-us/library/fkbw11z0.aspx

+0

Vâng, tôi biết điều đó. Nhưng câu hỏi là.DoSomeWork() và DoSomeMoreWork() có gây ra lặp lại danh sách lớn hay không, chúng sẽ chỉ lặp lại tập hợp con. – Christoph

+0

@Christoph - câu trả lời được chỉnh sửa ngay bây giờ ..... –

+0

Tốt hơn để sử dụng .ToArray rằng ToList để sử dụng này: mảng là phần nào hiệu quả hơn, nhưng quan trọng nhất, chúng không cho phép thêm/loại bỏ, tránh tính linh hoạt không cần thiết (do đó tránh nhầm lẫn và lỗi). –

1

Danh sách lớn sẽ được nhắc lại hai lần. nếu bạn không muốn nó, bạn có thể "thực hiện" các hạn chế.

var filtered = testList.Where(x => x == "Test1").ToList(); 

Và có nhiều câu trả lời cho bạn biết điều này. Bạn nên đã tìm kiếm tốt hơn :-)

0

nó sẽ trở nên thông minh hơn để làm cho "lọc" một danh sách (aka sử dụng var và chỉ cần thêm ToList() ở cuối)

Có, đặc biệt là trong điều khoản của LINQ-To-Entities, v.v.

Trả lại IEnumerable bằng LINQ cho phép thực hiện khác nhau. Khi bạn nối thêm ToList() vào cuối, danh sách của bạn sẽ được trả về ngay tại đó.

Xem http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx

7

Danh sách lớn sẽ được nhắc lại hai lần. Để kiểm tra điều này thực sự xảy ra thay đổi truy vấn của bạn để:

List<string> testList = new List<string> { "Test", "Test1", "Test1" }; 
IEnumerable<string> filtered = from t in testList 
           where t == "Test1" 
           select t; 

Nếu bạn sau đó thiết lập một breakpoint trên đó t == phần' Test1 ", bạn sẽ thấy rằng các debugger chạm dòng này cho cả các lần lặp lại.

+0

Ah, vâng. Đúng rồi. Cảm ơn gợi ý! – Christoph

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