静态析构函数


72

C#具有静态构造函数,可以进行一些初始化(可能会进行一些非托管资源的初始化)。

我想知道是否有静态析构函数?


1
为这个有趣的评论+1,嬉皮士。我想指出的是,静态资源与应用程序的生存期基本相同。他们死于应用程序死亡。因此,不需要静态析构函数。
decyclone 2010年

4
“因此不需要静态析构函数”-这两件事有什么关系?因为只有在卸载appdomain时才会发生,所以突然没有必要了吗?我不确定我是否遵循那里的逻辑。
BrainSlugs83

Answers:


38

不,没有。

静态析构函数应该在进程执行结束时运行。当进程终止时,与该进程关联的所有内存/句柄将被操作系统释放。

如果您的程序应在执行结束时执行特定的操作(例如事务数据库引擎,刷新其缓存),则正确处理的难度将比仅在正常执行结束时运行的一段代码困难得多。过程。您必须手动处理崩溃和进程意外终止,然后无论如何都要尝试在下次运行时进行恢复。“静态析构函数”的概念无济于事。


5
就我而言,我使用的是需要发布的操作系统范围的Mutex,否则它将在应用程序的下一次运行时引发AbandonedMutexException。在这种情况下,程序末尾释放的内存和句柄没有说明我的Mutex。您在第三段中所说的可能是一种管理它的方法,但是应用程序发行的结束对我来说似乎更有意义。
user1132959 2014年

108

并非完全是析构函数,但是您将执行以下操作:

class StaticClass 
{
   static StaticClass() {
       AppDomain.CurrentDomain.ProcessExit +=
           StaticClass_Dtor;
   }

   static void StaticClass_Dtor(object sender, EventArgs e) {
        // clean it up
   }
}

1
尽管该事件似乎发生在AppDomain上,但实际上仅在整个应用程序终止之前,默认域退出时(即最后一个域)才触发。卸载任何其他AppDomain时,它不会触发,这本身将导致大多数类型和类型的实例被破坏(但并非总是如此)。不能保证此事件总是会触发。
亚伯2015年

1
我建议不要将敏感的清除操作留给静态实例的解构,并且遵循此建议,您无需担心此事件不会触发。我从来没有遇到过此事件不会触发的问题(即使应用程序中发生了意外的异常)。通过任务管理器终止进程与意外异常有很大不同。没错,但是如果用户通过OS任务管理系统杀死程序,则不会触发。
zackery.fix

1
将销毁代码添加到创建应用程序域的Main()方法的末尾是个好主意吗?
佛罗伦萨

69

这是最好的方法(ref:https : //stackoverflow.com/a/256278/372666

public static class Foo
{
    private static readonly Destructor Finalise = new Destructor();

    static Foo()
    {
        // One time only constructor.
    }

    private sealed class Destructor
    {
        ~Destructor()
        {
            // One time only destructor.
        }
    }
}

4
这样可以保证工作!:)放手一搏,我有单元测试来证明如果有人感兴趣的话,它可以工作吗?
Tod Thomson

1
这是一种与环境无关的方式(在语言逻辑内部
构建

8
不幸的是,这不能保证有效。Per Raymond Chen的有关垃圾回收终结器的文章并不可靠,因为无法保证GC会运行。
McGuireV10

@ McGuireV10(我不是说你在这里是错的),但对终结的官方文档中不包含任何提及什么雷蒙德说docs.microsoft.com/en-us/dotnet/csharp/programming-guide/...它听到微软关于他在2010年发表的文章是否(或仍然是)准确的报道会很有趣吗?在上述所有测试中,我从未触发过终结器未调用的情况...如果以上建议不正确,那么我想更新/删除它,但我认为我们需要更强有力的证据。
Tod Thomson

@TodThomson对于.NET Framework,〜Object备注部分列出了无法保证终结器的某些情况,并且您链接的文档指出,在.NET Core下关闭时不会调用它们。不幸的是,MS文档的质量已不如从前。
McGuireV10

17

不,没有。您可以做的最接近的事情是在上为该DomainUnload事件设置事件处理程序,AppDomain并在那里进行清理。


4
实际上,对于更高Process_Exit建议的建议,这是非常可取的方法,这是完全不同的。静态ctor触发后,类型的生存期通常是程序集的生存期,该生命周期随AppDomain一起卸载。
亚伯2015年

1
对我来说,这是最简单,影响最小的解决方案。在我的上下文中,钩住Process_Exit无效,但DomainUnload起作用。
Brian Wirt

6

从静态实现初始化和清除非托管资源非常成问题,并且容易出现问题。

为什么不使用单例并Finalizer为实例实现(理想情况是继承自SafeHandle


1

没有,没有像静态类的析构函数Appdomain.Unloaded那样的东西了,但是如果确实需要做一些事情,那么可以使用事件

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.