【问题标题】:wrong to use a deconstructor?使用解构器错了吗?
【发布时间】:2011-04-07 13:19:13
【问题描述】:

我有一些文件写入 c# 中的临时位置。然后将它们呈现为 pdf 缩略图。当对象被销毁时,我希望清理该位置,那么在这种情况下可以使用解构函数吗?

    ~Foo()
    {
        try
        {
            Directory.Delete(path, true);
        }
        catch (IOException ex)
        {
            Console.WriteLine("exception: " + ex.Message + " . from: Foo_Closing");
        }

【问题讨论】:

    标签: c# garbage-collection finalizer


    【解决方案1】:

    尽管它具有与 C++ 析构函数相同的语法,但它是 C# 中的 finalizer,当对象在终结时被垃圾回收时运行 - 这将对性能产生影响,因为 GC 必须运行单独的线程来运行所有终结器,这样做你的对象实例将比必要的寿命更长。

    如果你不是绝对必须的话,你不应该使用它——一个例外是你必须处理资源,在这种情况下你的类也应该实现IDisposable。这将允许您的类的使用者将其包装在一个 using 块中,该块将调用 Dispose() - 这是您应该拆除资源的地方。

    【讨论】:

    • 以上不是说 rudley btw :) 你刚刚告诉我当时我不应该做什么。
    • @ricki:明白了——我在答案中添加了:实现IDisposable 并在那里处理资源——在实例化你的类时使用using 块,也在你的终结器中调用Dispose()。如果可能,请提前删除临时文件夹或使用系统临时文件夹
    【解决方案2】:

    您应该实现 IDisposable 接口,并在其中进行清理。

    【讨论】:

      【解决方案3】:

      解构器(也称为析构器或终结器)的问题在于您无法预测它们何时会运行,因为它们是由垃圾收集器调用的。为了获得可预测的行为,您应该实现 IDisposable 并显式调用 Dispose(或使用 using 块中的对象)

      你也可以从析构函数中调用Dispose,以防它没有被显式调用。请参阅this page 了解推荐使用的模式。

      【讨论】:

      • +1 用于使用 - 可能值得指出的是,正确实现 IDisposable 可能有点棘手,并且一次性成员意味着包含类需要是一次性的(这让一次性成员有点头疼)跨度>
      【解决方案4】:

      我可能只是使用环境的临时文件/文件夹位置,以便用户或管理员可以在正常的内务处理过程中清理文件。

      不要费心这样做,因为它带有 hack 的味道 - 在那里删除文件夹真的那么重要吗?

      【讨论】:

      • 是的,因为 - 对于特定搜索,我只希望显示返回的 pdf,如果我等待用户清理,则文件夹将填充旧内容和新内容
      • 您能否在进行搜索之前清理文件夹?
      【解决方案5】:

      尽可能避免实现终结器。您无法控制它们何时被调用,并且它们会导致性能损失,因为运行时需要特别处理具有终结器的对象。一般来说,只有当你有一个原生对象句柄或其他需要清理的原生资源时,你才应该实现终结器。

      相反,在您的类上实现 IDisposable 接口,将您的清理代码移至 Dispose 方法,并确保您的所有客户端都调用 Dispose 方法(using 语句很方便)。

      【讨论】:

        【解决方案6】:

        改为实现 IDisposable 接口:

        public class tester : IDisposable
        {
            #region IDisposable Members
        
            public void Dispose()
            {
                //cleanup code here
            }
        
            #endregion
        }
        
        using (tester t = new tester())
        {
        
        }
        //tester now disposed 
        

        但不要忘记this gem of knowledge from MSDN:

        因为 Dispose 方法必须是 显式调用,对象 实施 IDisposable 也必须 实现一个终结器来处理 Dispose 不在时释放资源 叫

        因此,您还应该实现终结器以及 IDisposable 接口,记住两者都会被调用。

        【讨论】:

        • 但是这里的“释放资源”指的是原生资源,比如对打开的文件的句柄之类的,不是吗?像文件系统中的文件这样的外部性,在你的代码中没有打开,在这种情况下不作为“资源”应用。
        • “资源”这个词有点不清楚。资源不是“事物”——它是一种责任,只有某些特定对象才有信息和动力来执行。在程序退出之前创建一个应该被删除的文件就是这样的责任;不过,我对在 Finalize 方法(C# 令人讨厌地称之为“析构函数”)中删除文件有点谨慎,因为各种因素可能导致此类操作失败或被阻塞任意长时间。另请注意,终结器有时可能会在预期之前运行,从而造成麻烦。
        【解决方案7】:

        为什么不使用 IDisposable 接口,然后你可以用“using”来包装你的调用,Dispose() 将执行它需要执行的所有清理

        public class Foo : IDisposable { public void Dispose() { //Clean up here}
        }

        using (foo = new Foo() ) { //consume foo here }

        【讨论】:

          【解决方案8】:

          有一个选项可以在关闭时删除临时文件,如果您能够利用它没关系,对吧?试试这些链接

          1. Handling with temporary file stream
          2. http://msdn.microsoft.com/en-us/library/system.io.fileoptions.aspx
          3. http://www.codeproject.com/KB/system/Taking_care_of_temp_files.aspx?msg=3489384

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-08-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多