2009-06-26 28 views
21

Tôi đang kiểm tra mã trong phản xạ, nhưng tôi chưa tìm ra cách nó có thể liệt kê thông qua một bộ sưu tập ngược?Làm thế nào để IEnumerable <T> .Reverse làm việc?

Vì không có thông tin tính và liệt kê luôn bắt đầu từ "bắt đầu" của bộ sưu tập, phải không?

Đây có phải là nhược điểm trong khuôn khổ .NET không? Chi phí cao hơn so với điều tra thường xuyên?

+0

Không có phương thức IEnumerable .Reverse mà tôi từng thấy (và MSDN dường như hỗ trợ điều này)! – Noldorin

+8

Đó là bởi vì đó là một phương pháp mở rộng: http://msdn.microsoft.com/en-us/library/bb358497.aspx –

+2

@Noldorin: Enumerable.Reverse là một phương pháp mở rộng trên IEunumerable

Trả lời

40

Tóm lại, nó đệm tất cả mọi thứ và sau đó đi qua nó ngược. Không hiệu quả, nhưng sau đó, không phải OrderBy từ quan điểm đó.

Trong LINQ-to-Objects, có các hoạt động đệm (Reverse, OrderBy, GroupBy, vv) và các hoạt động không đệm (ở đâu, Take, Skip, v.v.).


Như một ví dụ về một tổ chức phi đệm Reverse thực hiện sử dụng IList<T>, hãy xem xét:

public static IEnumerable<T> Reverse<T>(this IList<T> list) { 
    for (int i = list.Count - 1; i >= 0; i--) { 
     yield return list[i]; 
    } 
} 

Lưu ý rằng điều này vẫn còn một chút nhạy cảm với lỗi nếu bạn đột biến danh sách trong khi lặp lại nó ... do đó, đừng làm điều đó ;-p

+0

Cảm ơn Marc. Bằng cách đệm, bạn có nghĩa là nó sao chép toàn bộ bộ sưu tập, như Levi nói? –

+3

Chính xác, vâng. –

+0

Cảm ơn Marc. Ngoài sự tò mò, bạn có biết liệu một điều tra tốt hơn có thể được thực hiện không, với một giao diện mới? Tôi luôn luôn nghĩ IEnumerable là tốt (và nó là), nhưng liệu một trong những sẽ có thể thiết kế một trong đó sẽ thực hiện tốt hơn trong các trường hợp này quá? –

6

Nó hoạt động bằng cách sao chép IEnumerable <T> cơ bản vào một mảng, sau đó đếm ngược mảng đó. Nếu IEnumerable số <T> thực hiện ICollection <T> (như T [], Danh sách <T>, v.v.), thì bước sao chép bị bỏ qua và điều tra viên chỉ lặp lại trực tiếp bộ sưu tập bên dưới.

Để biết thêm thông tin, hãy xem System.Linq.Buffer <TElement> trong Trình phản xạ.

Chỉnh sửa: Bộ sưu tập cơ bản luôn được sao chép, ngay cả khi đó là ICollection <TElement>. Điều này ngăn cản các thay đổi trong bộ sưu tập cơ bản được tuyên truyền bởi Bộ đệm <TElement>.

+0

Tôi đang xem bộ đệm Buffer và tôi không thể thấy bất kỳ lúc nào khi bỏ qua bước sao chép - cẩn thận để xây dựng? –

+0

@Marc, @Levi: Nó vẫn tạo một bản sao, nhưng có sử dụng phương pháp ICollection .CopyTo thay vì liệt kê chuỗi. – LukeH

3

nó tải tất cả các mục vào bộ nhớ và sau đó thực hiện các bước qua chúng (ngược). điều này kém hiệu quả hơn nhiều.

-3

Chỉnh sửa: Opps, viết sai kiểm tra ngược lại, lời xin lỗi của tôi cho câu trả lời sai. Nó có bộ đệm sau khi kiểm tra hiệu chỉnh (sử dụng số đếm được trả về bởi Đảo ngược())

Có vẻ như phương pháp mở rộng đảo ngược chỉ hoạt động khi tập hợp được điền. Trong khi sử dụng lợi nhuận, nó không làm gì cả.

Biến thành vấn đề bằng cách sử dụng suy nghĩ ngược lại nó phải đệm cho nó hoạt động, thấy nó không hoạt động với năng suất. Nó chỉ vượt qua nó và không làm gì cả. dưới đây là mã thử nghiệm của tôi.

 [TestMethod] 
    public void loopTest() 
    { 
     var series = this.GetSeries(); 

     series.Reverse(); 

     foreach (var l in series) 
     { 
      Debug.WriteLine(l); 
     } 
    } 

    private IEnumerable<long> GetSeries() 
    { 
     var series = new List<long>() { 1, 2, 3, 4 }; 

     foreach (var entry in series) 
     { 
      Debug.WriteLine(entry); 

      yield return entry; 
     } 
    } 

Đảo ngược không gọi hàm GetSeries, tất cả các cuộc hội thoại đệm trong diễn đàn này trông từ không khí mỏng.

+1

Phương pháp mở rộng đảo ngược không thực sự đảo ngược bộ sưu tập cơ bản. Thay vào đó, nó tạo ra một enumerable mới mà sẽ liệt kê các bộ sưu tập theo thứ tự ngược lại. Dòng của bạn trông như thế này 'series.Reverse();' không có hiệu lực. Nếu bạn thay đổi dòng để trông như thế này 'var reversed = series.Reverse();' và sau đó lặp qua 'đảo ngược', tnen bạn sẽ nhận được câu trả lời đúng. – wageoghe

+0

Cảm ơn lương, vì đã chỉ ra vấn đề. – mamu

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