2010-02-17 32 views
30

Có bất kỳ ý nghĩa nào để đặt đối tượng tùy chỉnh thành null (Nothing trong VB.NET) theo phương thức Dispose() không? Điều này có thể ngăn chặn rò rỉ bộ nhớ hoặc nó vô dụng ?!Bất kỳ ý nghĩa nào để đặt obj = null (Không có gì) trong Dispose()?

Hãy xem xét hai ví dụ:

public class Foo : IDisposable 
{ 
    private Bar bar; // standard custom .NET object 

    public Foo(Bar bar) { 
     this.bar = bar; 
    } 
    public void Dispose() { 
     bar = null; // any sense? 
    } 
} 

public class Foo : RichTextBox 
{ 
    // this could be also: GDI+, TCP socket, SQl Connection, other "heavy" object 
    private Bitmap backImage; 

    public Foo(Bitmap backImage) { 
     this.backImage = backImage; 
    } 

    protected override void Dispose(bool disposing) { 
     if (disposing) { 
      backImage = null; // any sense? 
     } 
    } 
} 

Trả lời

19

Mục đích của Dispose() là cho phép dọn dẹp các nguồn lực không được xử lý bởi các nhà sưu tập rác. Các đối tượng được GC xử lý, do đó, thực sự không cần thiết lập tham chiếu đến null trong các trường hợp bình thường.

Trường hợp ngoại lệ là nếu bạn mong đợi người gọi gọi số Dispose giữ lại bản sao sau đó. Trong trường hợp đó, có thể là một ý tưởng hay để đặt tham chiếu nội bộ thành null. Tuy nhiên, các trường hợp dùng một lần thường được xử lý và phát hành cùng một lúc. Trong những trường hợp này, nó sẽ không tạo nên sự khác biệt lớn.

+0

Trong ví dụ thứ hai của tôi, tôi có Bitmap, được đề xuất Vứt bỏ(). Bây giờ, khi Bitmap không được tạo bởi đối tượng Foo nhưng chỉ được truyền vào tham số, tôi không thể thực hiện nó. Tôi nghĩ đặt nó ít nhất là để Null ... – serhio

+4

Bạn luôn phải quyết định nơi làm sạch phụ thuộc diễn ra. Nếu bạn biết rằng bitmap không được sử dụng ở bất kỳ nơi nào khác, Foo nên gọi 'Dispose()'. Nếu không, nó chỉ nên để nó và để người gọi xử lý việc dọn dẹp. Không có lợi ích bổ sung trong việc đặt tham chiếu cục bộ thành rỗng. Khi thể hiện của Foo được khai hoang, đó là thể hiện của Bitmap trừ khi người gọi vẫn giữ một tham chiếu đến nó. –

+2

@serhio - nếu bạn muốn giải phóng tài nguyên được sử dụng bởi đối tượng Bitmap của bạn ngay sau khi bạn sử dụng nó trong Foo (không ai khác đang sử dụng nó), thì Foo.Dispose nên gọi backImage.Dispose – Gishu

0

Mục đích của dispose() là xóa các tài nguyên không được quản lý. Kết nối TCP, kết nối cơ sở dữ liệu và các đối tượng cơ sở dữ liệu khác và rất nhiều tài nguyên không được quản lý như vậy được cho là do nhà phát triển phát hành trong phương thức vứt bỏ. Vì vậy, nó thực sự có ý nghĩa.

+0

cho cả hai ví dụ với bitmap GDI + và thanh đối tượng .NET tùy chỉnh đơn giản? Tôi không vứt bỏ chúng, nguyên nhân được truyền trong tham số và không được tạo bởi đối tượng. – serhio

23

Cá nhân tôi có xu hướng; vì hai lý do:

  • nó có nghĩa rằng nếu ai đó đã quên để giải phóng Foo (có lẽ từ một sự kiện) bất kỳ đối tượng hạ lưu (một Bitmap trong trường hợp này) vẫn có thể được thu thập (tại một số điểm trong tương lai - bất cứ khi nào GC cảm thấy thích nó); nó là có khả năng là rằng đây chỉ là một trình bao bọc cạn xung quanh một tài nguyên không được quản lý, nhưng mọi thứ đều giúp ích.
    • I thực sự không thích vô tình giữ toàn bộ biểu đồ đối tượng treo xung quanh chỉ vì người dùng quên bỏ ghim một sự kiện; IDisposable là một công cụ "gần như giết" tiện dụng - tại sao không tách mọi thứ sẵn có?
  • quan trọng hơn, tôi có thể xấc xược hiện nay sử dụng lĩnh vực này để kiểm tra (trong phương pháp vv) để xử lý, ném một ObjectDisposedException nếu nó là null
+1

Bạn có thường xuyên tham chiếu đến các đối tượng sau khi gọi Dispose() trên chúng không? –

+8

@Brian - lưu ý các từ "vô tình" và "sự kiện"; và lưu ý rằng ** Tôi không nhất thiết phải là người viết mã * sử dụng * thành phần của tôi. Tôi không thể sửa mã * của họ, nhưng tôi có thể làm cho tôi cư xử tốt. –

+0

@Dave - làm rõ –

4

Đó là chỉ là về vô dụng. Thiết lập để NULL trở lại trong ngày COM/VB cũ, tôi tin rằng, sẽ giảm số lượng tham chiếu của bạn.

Điều đó không đúng với .NET. Khi bạn thiết lập thanh thành null, bạn không phá hủy hoặc giải phóng bất cứ thứ gì. Bạn chỉ cần thay đổi tham chiếu mà thanh trỏ đến, từ đối tượng của bạn thành "null". Đối tượng của bạn vẫn tồn tại (mặc dù bây giờ, vì không có gì đề cập đến nó, nó cuối cùng sẽ được thu gom rác). Với vài trường hợp ngoại lệ, và trong hầu hết các trường hợp, đây là điều tương tự đã xảy ra nếu bạn chưa thực hiện Foo IDisposable ngay từ đầu.

Mục đích lớn của IDisposable là cho phép bạn phát hành tài nguyên không được quản lý, như cổng TCP hoặc kết nối SQL hoặc bất kỳ thứ gì. Điều này thường được thực hiện bằng cách gọi bất kỳ chức năng dọn dẹp nào mà tài nguyên không được quản lý cung cấp, không phải bằng cách đặt tham chiếu thành "null".

+1

OK, nếu thay vào đó * Bar * Tôi có một * TCP socket *? Nó có nên vô ích để thiết lập nó để null? vì nó được truyền bởi tham số và "ai đó" có thể sử dụng đối tượng này ... – serhio

+1

Vâng, nó sẽ là vô dụng. Nếu bạn có một socket TCP, bạn sẽ giải phóng nó bằng cách gọi phương thức .Close() của socket. Tương tự với SQL Connections. Đặt thành "null" thực sự không làm gì ngoài thay đổi tham chiếu của bạn thành đối tượng bạn đang sử dụng. –

+1

-1, đặt thành không có gì cho phép bộ thu gom rác dọn sạch vào lần vượt qua đầu tiên. – AMissico

1

Điều này có thể có ý nghĩa nếu bạn muốn bằng cách nào đó ngăn chặn trường hợp được sở hữu đã xử lý được sử dụng lại.

Khi bạn đặt tham chiếu đến các trường dùng một lần thành không, bạn được đảm bảo không sử dụng các phiên bản nữa.

Bạn sẽ không nhận được ObjectDisposedException hoặc bất kỳ trạng thái không hợp lệ nào khác do sử dụng trường hợp đã được xử lý thuộc sở hữu (bạn có thể nhận được NullReferenceException nếu bạn không kiểm tra giá trị rỗng).

Điều này có thể không có ý nghĩa đối với bạn miễn là tất cả IDisposable đối tượng có một tài sản IsDisposed và/hoặc ném ObjectDisposedException nếu chúng được sử dụng sau khi được xử lý - một số có thể vi phạm nguyên tắc này và cài đặt chúng thành vô giá trị có thể ngăn ngừa tác động không mong muốn từ xảy ra.

1

Trong C# thiết lập một đối tượng là null chỉ cần giải phóng tham chiếu đến đối tượng. Vì vậy, về mặt lý thuyết tốt hơn là giải phóng tham chiếu trên các đối tượng được quản lý trong Phương thức Vứt bỏ trong C#, nhưng chỉ cho khả năng GC thu thập đối tượng được tham chiếu trước khi đối tượng được xử lý được thu thập. Vì cả hai đều có khả năng sẽ được thu thập trong cùng một lần chạy, GC sẽ dễ dàng nhận ra nhất, rằng đối tượng được tham chiếu chỉ được tham chiếu bởi một loại được xử lý, vì vậy cả hai có thể được thu thập.

Ngoài ra cần phải giải phóng tham chiếu là rất nhỏ, vì tất cả các thành viên công cộng của lớp dùng một lần của bạn nên ném một ngoại lệ nếu lớp học được phân phối. Vì vậy, không có quyền truy cập đối tượng được tham chiếu của bạn sẽ thành công sau khi xử lý phương thức được tham chiếu.

+0

Thx Dave, thay đổi thông tin về VB.NET –

+0

Vì vậy, sự khác biệt giữa C# và VB.NET khi thiết lập Không là gì? Tôi tiếp xúc với câu hỏi trong C# để dễ đọc, nhưng dự án thực sự của tôi là trong VB.NET. – serhio

+2

Vì mục đích của bạn, không có sự khác biệt. Nhưng VB.NET là một ngôn ngữ khủng khiếp. Trong VB.NET, nếu bạn đặt Dim x là số nguyên = không có gì, và sau đó in giá trị của "x", bạn nhận được 0. Trong C# nó chỉ không biên dịch vì "int" là một kiểu giá trị và "null" là nghiêm chỉnh một tham chiếu. Vì vậy, họ không cư xử chính xác như nhau. Nhưng đối với các loại tham chiếu như đối tượng IDisposable, chúng hoạt động giống hệt nhau. –

1

Trong VB.NETlà cảm giác để thiết lập để Nothing tuyên bố Private WithEvents đối tượng.

Trình xử lý sử dụng Handles từ khóa sẽ bị xóa theo cách này từ các đối tượng này.

0

Nói chung không cần phải đặt thành rỗng. Nhưng giả sử bạn có một chức năng Reset trong lớp của bạn.

Sau đó, bạn có thể làm, bởi vì bạn không muốn gọi xử lý hai lần, vì một số Xử lý có thể không được triển khai đúng và ném ngoại lệ System.ObjectDisposed.

private void Reset() 
{ 
    if(_dataset != null) 
    { 
     _dataset.Dispose(); 
     _dataset = null; 
    } 
    //..More such member variables like oracle connection etc. _oraConnection 
} 
Các vấn đề liên quan