2011-11-22 6 views
6

Về cơ bản tôi có một vài chức năng mà trông như thế này:Sử dụng câu lệnh trong mọi chức năng -> chuyển đổi sang trường lớp bằng cách dọn dẹp thích hợp?

class MyClass 
{ 
    void foo() 
    { 
     using (SomeHelper helper = CreateHelper()) 
     { 
      // Do some stuff with the helper 
     } 
    } 

    void bar() 
    { 
     using (SomeHelper helper = CreateHelper()) 
     { 
      // Do some stuff with the helper 
     } 
    } 
} 

Theo giả thiết tôi có thể sử dụng tài nguyên cùng thay vì một khác nhau [ví dụ] trong mỗi chức năng là nó thực hành ok liên quan đến dọn dẹp và như vậy để làm điều này?:

class MyClass 
{ 
    SomeHelper helper = CreateHelper(); 

    // ...foo and bar that now just use the class helper.... 

    ~MyClass() 
    { 
     helper.Dispose(); 
    } 
} 
+2

Thay vì sử dụng finalizer bạn có thể thay vào đó (nếu có thể) thực hiện 'IDisposable' trong 'MyClass' và khi Vứt bỏ cuộc gọi' helper.Dispose' –

Trả lời

8

Không, làm không thêm trình phá hủy (Trình kết thúc).

Bạn có thể sử dụng lại tài nguyên nhưng sau đó lớp học của bạn phải triển khai IDisposable.

sealed class MyClass : IDisposable 
{ 
    SomeHelper helper = CreateHelper(); 

    // ...foo and bar that now just use the class helper.... 

    //~MyClass() 
    public void Dispose()  
    { 
     helper.Dispose(); 
    }       
} 

Và bây giờ bạn phải sử dụng MyClass trường hợp trong khối sử dụng. Bản thân nó đã trở thành một tài nguyên được quản lý .

Một destructor là không sử dụng, bất cứ khi nào một cá thể MyClass đang được thu thập các đối tượng trợ giúp liên quan cũng sẽ có trong cùng một bộ sưu tập. Nhưng có một destructor vẫn phải chịu chi phí đáng kể.

standard pattern cho IDisposable sử dụng phương thức virtual void Dispose(bool disposing) nhưng khi tạo lớp học sealed bạn có thể sử dụng triển khai tối giản ở trên.

+0

Could I rắc rối cho bạn một lời giải thích lý do tại sao? (Tôi giả định bởi câu trả lời của bạn destructor là một ý tưởng tồi) –

+0

Vâng, destructor là tốn kém và vô dụng. Đã chỉnh sửa. –

+0

Ngoài ra Finalizers không được bảo đảm để được gọi bất cứ lúc nào cụ thể, mà có thể phá vỡ các hành vi bạn mong muốn làm việc (chủ yếu là do không nhận ra finalizers trong C# không giống như destructors trong C + +). –

1

Bạn có thể chia sẻ như một nguồn tài nguyên trong suốt thời gian tồn tại của đối tượng của bạn, trong trường hợp này nó được khuyến khích mà bạn implement IDisposable.

1

Quy ước là nếu lớp của bạn sở hữu đối tượng IDisposable, nó cũng phải triển khai IDisposable. Vì vậy, thay vì thực hiện một finalizer lớp của bạn nên thực hiện IDisposable và dipose của helper ở đó.

Một vấn đề với việc triển khai finalizer là bạn không thể kiểm soát được khi nó được gọi. Các mô hình dùng một lần cung cấp cho bạn một cách xác định hơn để làm sạch tài nguyên.

1

Không, không phải. Bạn không biết khi nào finalized sẽ un. Ngoài ra, nếu tài nguyên của bạn được quản lý, nó sẽ được xử lý tại một số điểm mà không được hoàn thành.

Nếu bạn không muốn sử dụng mọi lúc, có lẽ bạn có thể sử dụng nó một lần quanh nhiều chức năng.

2

Trong .NET you don't know when (or whether) finalizer is called.

Thay vào đó, rõ ràng chỉ ra rằng lớp học của bạn là để được xử lý bởi implementing IDisposable:
(Đây chính là điều SomeHelper không)

class MyClass : IDisposable 
{ 
    readonly SomeHelper helper = CreateHelper(); 

    // any method can use helper 

    public void Dispose() 
    { 
     helper.Dispose(); 
    } 
} 

using(var myObj = new MyClass()) { 
    // at the end, myObj.Dispose() will trigger helper.Dispose() 
} 

tôi đã sử dụng để đảm bảo readonlyhelper không nhận lại được chỉ định ở một nơi khác trong lớp, nhưng điều này thực sự không quan trọng nếu bạn cẩn thận.

Bạn phải cẩn thận hơn để không bao giờ đặt thành null hoặc Dispose của bạn sẽ ném một ngoại lệ.Nếu trường là protected, bạn có thể kiểm tra tính rỗng trước khi gọi số Dispose trên đó để bạn biết mình đang chơi an toàn.

1

Bạn không cần ghi đè trình hoàn thiện trong đối tượng của mình, mà bạn đã hiển thị trong mẫu mã thứ hai của mình theo ~MyClass().

Bạn cần triển khai mẫu IDisposable. Bạn chưa rõ ràng trong câu hỏi của mình nếu bạn đang sử dụng tài nguyên được quản lý và không được quản lý, nhưng đây là mẫu nhanh cho tài nguyên được quản lý. Stackoverflow có vô số ví dụ về điều này. Reed Copsey cũng có một chuỗi tốt về nó, và bạn có thể bắt đầu here.

class MyClass : IDisposable 
{ 
    private bool _Disposed; 
    private SomeHelper _Helper; 
    protected virtual void Dispose() 
    { 
     this.Dispose(true); 
    } 
    public void Dispose(bool disposing) 
    { 
    if (_!Disposed && disposing) 
    { 
     if (_Helper != null) 
      _Helper.Dispose(); 
     _Disposed = true; 
    } 
    } 
}