2009-11-17 43 views
5

LINQ cho phép bạn tạo đối tượng mới bên trong biểu thức truy vấn. Điều này rất hữu ích khi bạn có các lớp đóng gói thế hệ danh sách. Tôi tự hỏi làm thế nào bạn xử lý các đối tượng được tạo ra mà cần nó?Làm thế nào để bạn loại bỏ IDisposableobject tạo bên trong một biểu thức LINQ?

Ví dụ:

class Generator 
{ 
    public IEnumerable<int> Gen(int size) 
    { 
     return Enumerable.Range(0, size); 
    } 
} 

class bar 
{ 
    public void doit() 
    { 
     var foo = 
      from r in Enumerable.Range(1, 3) 
      from g in new Generator().Gen(r) 
      select g; 
    } 
} 

này sẽ tạo ra 3 đối tượng Generator mà sẽ được thu gom rác tại một số điểm. Nếu Generator là IDisposable thì tôi sẽ nhận được lệnh Dispose() như thế nào?

+0

Câu hỏi tuyệt vời. Tôi có cùng một vấn đề, chỉ có tôi đang sử dụng từ khóa let. – Marcel

Trả lời

5

OK; Tôi hy vọng đây là sự trùng hợp, nhưng: SelectMany; combining IDisposable and LINQ, mà (với việc thực hiện tùy chỉnh SelectMany) sẽ cho phép:

var foo = 
     from r in Enumerable.Range(1, 3) 
     from gen in new Generator() 
     from g in gen.Gen(r) 
     select g; 

(lưu ý rằng tôi giả có một lý do hợp lý để thực hiện điều này mỗi r)

SelectMany

hoặc với phương pháp Using() mở rộng (thay vì SelectMany):

var foo = 
     from r in Enumerable.Range(1, 3) 
     from gen in new Generator().Using() 
     from g in gen.Gen(r) 
     select g; 

Using

+0

Bài đăng trên blog của bạn đã được định thời gian hoàn hảo. Tôi muốn sử dụng các đối tượng như DirectoryEntry bên trong mã LINQ nhưng không muốn rời khỏi tài nguyên hệ điều hành còn lại chưa được xác nhận. – Jason

+0

@Mark, có cách nào để thực hiện việc này cho Chọn không? Tôi đã thử, nhưng có vẻ như 'ẩn' chức năng tích hợp và sẽ không cho phép tôi chọn bất cứ thứ gì * không * IDisposable ... – Benjol

+0

@Benjol - bạn có thể cung cấp thêm thông tin? Nguồn bạn đang chọn từ đâu? –

5

Không âm thanh như bạn nên tạo một đối tượng mới Generator trên mỗi lần lặp, cho một vài lý do:

  • Đó là khủng khiếp không hiệu quả phân bổ (và có khả năng deallocated) bộ nhớ liên tục và nhanh chóng.
  • Đối tượng Generator có thể được thiết kế chỉ cho một trường hợp để tạo ra giá trị cho một tập hợp các thông số nhất định. Tất nhiên, tôi có thể sai về điều này, vì vậy xin vui lòng làm rõ nếu cần thiết.

tôi khuyên bạn hãy thử như sau:

using (var gen = new Generator()) 
{ 
    var foo = 
     from r in Enumerable.Range(1, 3) 
     from g in gen.Gen(r) 
     select g; 
} 
+0

Phải, nhưng điều đó sẽ làm giảm đi tiêu đề câu hỏi một chút. –

+1

@Henk: Thật vậy, nhưng tôi nghĩ OP vẫn nhìn vào những thứ sai trái. :) – Noldorin

+0

Điều này sẽ hiệu quả nếu tôi chỉ tạo 1 đối tượng cần xử lý. Tôi thừa nhận ví dụ của tôi không cho thấy nhu cầu, nhưng bạn có thể giả định rằng các lớp thực sự phức tạp hơn. Thông thường tôi muốn tạo một đối tượng dùng một lần mới mỗi lần lặp của các vòng truy vấn. – Jason

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