2008-11-01 27 views
36

Cách nào đúng để thực hiện một số kết thúc tĩnh?Static Finalizer

Không có hàm hủy tĩnh. Sự kiện AppDomain.DomainUnload không được nâng lên trong miền mặc định. Sự kiện AppDomain.ProcessExit chia sẻ tổng thời gian của ba giây (cài đặt mặc định) giữa tất cả các trình xử lý sự kiện, vì vậy nó không thực sự có thể sử dụng được.

+2

Đầu tiên, trong C#, chúng ta cần thoát ra khỏi thói quen sử dụng finalizer và destructor interchangably. Một là xác định, cái kia thì không. Thật thú vị khi lưu ý rằng thông số C# nhận các điều khoản ngược từ CLR và các đặc tả ngôn ngữ .NET khác.Nó cũng thú vị để lưu ý rằng các ghi chú của ủy ban ngôn ngữ C# rõ ràng nói rằng không có lý do tại sao C# không thể có finalizers tĩnh. http://stackoverflow.com/a/1875149/56793 – JMD

Trả lời

27

Về cơ bản, bạn không thể. Thiết kế theo cách của bạn xung quanh nó đến mức tối đa có thể.

Đừng quên rằng một chương trình có thể luôn luôn chấm dứt đột ngột anyway - ai đó rút ra sức mạnh là ví dụ rõ ràng. Vì vậy, bất cứ điều gì bạn làm phải là "nỗ lực tốt nhất" - trong trường hợp này tôi chắc chắn là hy vọng rằng AppDomain.ProcessExit sẽ là đủ tốt.

Bạn cần làm gì, trong trường hợp cụ thể của bạn?

+1

Câu trả lời này liên quan đến câu trả lời của Michael như thế nào (vì có vẻ như có thể có các final final)? (Dù bằng cách nào tôi đồng ý rằng finalizers là không đáng tin cậy.) – mafu

+0

@ mafutrct: Câu trả lời của Michael không thực sự là một finalizer tĩnh. Đó là một trường tĩnh với tham chiếu đến một cá thể có trình hoàn thiện. Nó không giống nhau, mặc dù nó có thể có tác dụng tương tự. Tôi sẽ không sử dụng nó một cách cá nhân. –

+0

Thực ra, bạn hoàn toàn đúng. Cảm ơn vì đã giải thích! – mafu

6

Tôi sẽ đặt câu hỏi những gì bạn đang tải trong các phương pháp tĩnh cần được phát hành. Tôi chắc chắn sẽ không khuyên bạn nên làm những điều này trong một phương pháp tĩnh.

Điều đó nói rằng, phương pháp tĩnh của bạn có thể instanciate một đối tượng có phương thức hoàn thiện.

6

Hai giải pháp mà nhảy đến tâm trí:

  • Đừng sử dụng một lớp tĩnh. Nếu bạn sử dụng một lớp không tĩnh và khởi tạo nó, bạn không phải lo lắng về việc dọn dẹp nhiều.
  • Nếu đó không phải là một lựa chọn, tôi cho rằng đây là một tình huống tốt để sử dụng một singleton. Điều này sẽ khởi tạo một bản sao của đối tượng của bạn và có finalizer được gọi là trên lối ra, nhưng vẫn cho phép bạn đối xử với nó như một lớp tĩnh cho hầu hết các phần. Sau khi tất cả, lớp học của bạn là tĩnh đã và do đó chia sẻ hầu hết các lý do phổ biến không sử dụng một singleton.
39

Herfried Wagner đã viết một excellent article giải thích làm thế nào để thực hiện điều này - than ôi, bằng tiếng Đức (và VB). Tuy nhiên, mã phải dễ hiểu.

Tôi đã thử nó:

static readonly Finalizer finalizer = new Finalizer(); 

sealed class Finalizer { 
    ~Finalizer() { 
    Thread.Sleep(1000); 
    Console.WriteLine("one"); 
    Thread.Sleep(1000); 
    Console.WriteLine("two"); 
    Thread.Sleep(1000); 
    Console.WriteLine("three"); 
    Thread.Sleep(1000); 
    Console.WriteLine("four"); 
    Thread.Sleep(1000); 
    Console.WriteLine("five"); 
    } 
} 

Có vẻ như để làm việc chính xác theo cách tương tự như trường hợp AppDomain.ProcessExit làm: finalizer được ca. ba giây ...

+3

Đây là câu trả lời hay nhất khi bạn có thể gỡ lỗi "finaliser" theo cách này, trong khi AppDomain. ProcessExit ủy nhiệm không cho phép bạn gỡ lỗi nó (ít nhất là trong kinh nghiệm của tôi). –

0

Để trả lời câu trả lời của Michael Damatov (C#) dựa trên Herfried K. Wagner. (VB.NET) đây là phiên bản C++/CLI:

ref class MyClass 
{ 
     ref class StaticFinalizer sealed 
     { 
      !StaticFinalizer(); 
     }; 
     static initonly StaticFinalizer^ stDestr = gcnew StaticFinalizer(); 
} 

MyClass::StaticFinalizer::!StaticFinalizer() 
{ 
    System::Diagnostics::Debug::WriteLine("In StaticFinalizer!"); 
} 

P.S. Cũng giống như phương thức AppDomain.ProcessExit, phương thức này có thể không được gọi nếu quá trình được kết thúc bất thường (từ Trình quản lý Tác vụ chẳng hạn). Một lời cảnh cáo khác là nếu MyClass là chung (templated), giả thiết rằng hàm tạo tĩnh của nó và hàm hủy tĩnh sẽ được gọi không quá một lần cho mỗi lần thực hiện ứng dụng không còn hợp lệ nữa.