2011-10-18 5 views
5

Tôi biết kỹ thuật xử lý IDisposable theo cách truyền thống. Giả sử, trong phương thức phục vụ cửa sổ OnStop() Tôi kết thúc sứ điệp hàng đợi khách hàng:Xử lý bằng cách đặt thành null?

 if (client != null) 
     { 
      client.Dispose(); 
     } 

Đây là lần đầu tiên hôm nay tôi thấy một anh chàng làm điều đó theo cách này:

 using (client) 
     { 
      client = null; 
     } 

chính xác là gì xảy ra bên trong mình "sử dụng" hay anh ta vứt bỏ một cách chính xác?

Trả lời

4

Mã số using dựa trên đồng nghiệp của bạn sẽ hoạt động, nhưng được cho là quá mức cần thiết;

using(client) { 
    client = null; 
} 

là chủ yếu:

{ // scope here to denote that 'tmp' is not defined outside this scope 
    var tmp = client; 
    try { 
     client = null; 
    } finally { 
     if(tmp != null) tmp.Dispose(); 
    } 
} 

(không khá rằng trong mọi trường hợp, như có giá trị gia loại và thực hiện giao diện rõ ràng để suy nghĩ về).

Cá nhân, tôi chỉ sử dụng using cho toàn bộ điều có thể (ví dụ: trong mã ban đầu phân bổ khách hàng).

Một lần tôi có thể sử dụng này là một lười biếng:

using(client as IDisposable) { client = null; } // dispose if needed 

tức client là một cái gì đó ngoài tầm kiểm soát của tôi, và tôi không chắc chắn nếu nó thực hiện IDisposable hay không, nhưng nếu có, tôi cần phải phát hành nó.

+0

BTW, một điều tôi nghĩ rằng sẽ nâng cao khả năng sử dụng "sử dụng" sẽ là khả năng đặt rõ ràng "biến bóng" thành null, để đối tượng không được xử lý hoặc phiên bản "sử dụng" khác sẽ chỉ xử lý trong trường hợp có lỗi. Một nhà xây dựng, ví dụ, sau đó có thể "sử dụng" các lĩnh vực của đối tượng được xây dựng, và sau đó quyết định "giữ" chúng ngay trước khi nó trở lại. Có thể sử dụng try/finally blocks thay vì "using", nhưng chúng tiết kiệm hơn và ít rõ ràng hơn. – supercat

+0

@supercat IMO rằng kịch bản đã khá phức tạp - tốt hơn để được rõ ràng về nó, và hiểu những gì đang xảy ra (tức là tôi hài lòng với 'try' /' final' there) –

+0

Tôi chỉ nhìn vào mã một lần nữa và suy nghĩ Tôi đã tìm ra mục đích - nếu "khách hàng" là một lĩnh vực hoặc tài sản, tuổi thọ của nó có thể không bị giới hạn trong một khối "đang sử dụng". Trong một số trường hợp, có thể cần phải xóa một trường hoặc thuộc tính giữ một tham chiếu đến đối tượng trước khi gọi Dispose lên nó. Mã "sử dụng" được hiển thị ở đây sẽ ngắn gọn hơn việc tạo một biến tạm thời một cách rõ ràng, mặc dù cách tiếp cận tốt hơn là sử dụng thói quen "Zap" cho một mục đích như vậy. – supercat

3

Thoát khỏi

using (client) 
{ 
} 

client.Dispose() được gọi tự động cho bạn.
client = null nên được gọi ra khỏi mã đó theo ý kiến ​​của tôi.
Hãy nhớ rằng để sử dụng using(object) đối tượng nên triển khai giao diện IDisposable.

+2

Tại sao bạn nên downvote? Tôi đã nói điều gì sai, xin giải thích để tôi có thể sửa hoặc xóa câu trả lời của tôi ... – Marco

+0

Không, không có gì đặc biệt sai; đã có một vài downvotes lẻ được tạo bởi một người dùng; không có liên kết mạnh mẽ với bất kỳ người dùng nào tham gia vào chuỗi này. Chỉ là ... kỳ lạ, thực sự. –

+0

Cảm ơn @MarcGravell, chỉ để hiểu và (cuối cùng) tìm hiểu một cái gì đó mới ... – Marco

6

Câu lệnh using(){} lấy một bản sao của tham chiếu var để gán này với null không hiệu quả.

+0

nhưng cũng vô hại (nó không can thiệp với các cuộc gọi để xử lý) – Martijn

+0

Đồng ý trong trường hợp thứ hai bạn phải sao chép con trỏ một lần nữa. Nó không có ý nghĩa để làm cho Dispose ngầm bên trong việc vứt bỏ chính nó. Trong mọi trường hợp, bạn cũng cần một kiểm tra rỗng để tránh trường hợp ngoại lệ khi nhập lại. –

+1

@Martijn - vô hại? thường nhưng không phải nếu bạn muốn trì hoãn việc vứt bỏ 'client'. Hiếm nhưng có thể. –

0

Đối với tôi, nó có vẻ không hiệu quả chút nào. Vì client được thiết lập là null nên không có gì được tham chiếu để xử lý nữa, mặc dù đối tượng thực sự vẫn còn trong bộ nhớ, không được tham chiếu bởi bất kỳ biến nào (nó sẽ được thu thập rác sau này, nhưng điểm của việc sử dụng là gì?).

0

Nếu phạm vi "khách hàng" mở rộng ra ngoài khối "đang sử dụng", có vẻ như mã sẽ được xử lý trước khi kiểm soát rời khỏi khối "đang sử dụng" và tham chiếu đến đối tượng "khách hàng" không còn tồn tại sẽ bị hủy. Nulling ra các tham chiếu đến nó có thể là quan trọng nếu nó là một lĩnh vực, và có thể là quan trọng nếu nó là một tài sản gắn các sự kiện.

Tôi đoán rằng "khách hàng" là một trường hoặc thuộc tính và tác giả của mã "đang sử dụng" nghĩ rằng nó ngắn gọn hơn so với phiên bản do Marc Gravell đưa ra. Tôi sẽ cấp cho tác giả rằng đoạn mã ngắn gọn, nhưng sẽ gợi ý rằng ngắn gọn hơn và rõ ràng hơn sẽ xác định thói quen chung "Zap" chấp nhận một IDisposable bằng tham chiếu, sử dụng Interlocked.Exchange để đọc và bỏ nó, và xử lý nó nếu nó không phải là null.Trong trường hợp đó, tuyên bố "sử dụng" sẽ được thay thế bằng:

 
    Zap(ref client); 

có lợi ích ngắn gọn hơn trong khi gần như rõ ràng hơn.