类的析构问题 [英] Class Destructor Problem

查看:141
本文介绍了类的析构问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想提出一个包含StreamWrite

I am making a simple class that contains a StreamWrite

    class Logger
{
    private StreamWriter sw;
    private DateTime LastTime; 
    public Logger(string filename)
    {
        LastTime = DateTime.Now;
        sw = new StreamWriter(filename);
    }
    public void Write(string s)
    {
        sw.WriteLine((DateTime.Now-LastTime).Ticks/10000+":"+ s);
        LastTime = DateTime.Now;
    }
    public void Flush()
    {
        sw.Flush();
    }
    ~Logger()
    {
        sw.Close();//Raises Exception!
    }
}



但是,当我在析构函数关闭此StreamWriter的,它引发一个例外,该StreamWriter的已经被删除了?

But when I close this StreamWriter in the destructor, it raises an exception that the StreamWriter was already deleted?

为什么呢?
和如何使它发挥作用,这样当Logger类被删除,StreamWriter的被删除前关闭?

Why? And how to make it work such that when the Logger class is deleted, the StreamWriter is closed before deletion?

谢谢!

推荐答案

编写自己的析构函数(又名终结)是错误的所有病例99.99%。他们需要确保你的类释放未自动由.NET框架管理,未正确你类的用户发布了一个操作系统资源。

Writing your own destructor (aka finalizer) is wrong in 99.99% of all cases. They are needed to ensure that your class releases an operating system resource that isn't automatically managed by the .NET framework and wasn't properly released by the user of your class.

这将启动由不必在自己的代码首先分配的操作系统资源。这总是需要某种形式的P / Invoke的。这是的非常的很少用到,它是在微软工作照顾了.NET程序员的工作。

This starts by having to allocate the operating system resource first in your own code. That always requires some kind of P/Invoke. This is very rarely needed, it was the job of the .NET programmers working at Microsoft to take care of that.

他们做的案件的StreamWriter的。经过好几层,这是围绕一个文件句柄,与创建的CreateFile()的包装。创建该手柄的类也是一个最负责编写的终结。微软的源代码,不是你的。

They did in the case of StreamWriter. Through several layers, it is a wrapper around a file handle, created with CreateFile(). The class that created the handle is also the one that's responsible for writing the finalizer. Microsoft code, not yours.

这样的类总是实现IDisposable,给类的用户一个机会来释放资源,当它与它做,而不是等待为终结,以完成这项工作。 StreamWriter的实现IDisposable。

Such a class always implements IDisposable, giving the user of the class an opportunity to release the resource when it is done with it, rather than waiting for the finalizer to get the job done. StreamWriter implements IDisposable.

当然,你的StreamWriter对象是你的类的私有实现细节。当用户与您的Logger类做你不知道,你不能自动调用StreamWriter.Dispose()。你需要帮助。

Of course, your StreamWriter object is a private implementation detail of your class. You don't know when the user is done with your Logger class, you cannot call StreamWriter.Dispose() automatically. You need help.

获得通过实现IDisposable的自己,帮助。你的类的用户现在可以调用Dispose或使用using语句,就像她会与任何框架类的:

Get that help by implementing IDisposable yourself. The user of your class can now call Dispose or use the using statement, just like she would with any of the framework classes:

  class Logger : IDisposable {
    private StreamWriter sw;
    public void Dispose() {
      sw.Dispose();   // Or sw.Close(), same thing
    }
    // etc...
  }






好吧,这是你应该在所有的情况下,99.9%的做什么。但不是在这里。在致命混淆你的风险:如果你实现IDisposable,还必须有你的类调用它的Dispose()方法的用户一个合理的机会。这通常不是太大的问题,除了一个Logger类型的类。这是很可能的是你的用户想要登录的东西到最后一刻。这样她可以从AppDomain.UnhandledException记录未处理的异常,例如。


Well, that's what you should do in 99.9% of all cases. But not here. At the risk of fatally confusing you: if you implement IDisposable, there must also be a reasonable opportunity for the user of your class to call its Dispose() method. That is normally not much of a problem, except for a Logger type class. It is pretty likely that your user wants to log something up to the last possible moment. So that she can log an unhandled exception from AppDomain.UnhandledException for example.

当调用Dispose()在这种情况下?当你的程序终止,你可以做到这一点。但是,这还挺除了点,没有早期释放资源,如果它在程序退出时会发生多大意义。

When to call Dispose() in this case? You could do it when your program terminates. But that's kinda besides the point, there isn't much point in releasing resources early if it happens when the program is exiting.

一个记录器有特殊要求关闭正常在所有情况下。这就需要您在StreamWriter.AutoFlush属性设置为true使日志输出只要它被写入刷新。鉴于调用Dispose()正确,现在实际上是更好的,你不实现IDisposable,让微软的终结关闭该文件句柄的难度。

A logger has the special requirement to shut down properly in all cases. That requires that you set the StreamWriter.AutoFlush property to true so that logging output is flushed as soon as it is written. Given the difficulty of calling Dispose() properly, it is now actually better that you don't implement IDisposable and let Microsoft's finalizer close the file handle.

FWIW,还有另一种类中,具有相同的问题的框架。 Thread类使用四个操作系统处理,但并没有实现IDisposable。调用Thread.Dispose()是的真正的尴尬,因此微软没有实现它。这导致的非常的特殊情况下的问题,你需要编写一个创造了很多的线程,但从来没有使用new运算符来创建类对象的程序。 。它已经完成

Fwiw, there's another class in the framework that has the same problem. The Thread class uses four operating system handles but doesn't implement IDisposable. Calling Thread.Dispose() is really awkward, so Microsoft didn't implement it. This causes problems in very unusual cases, you'd need to write a program that creates a lot of threads but never uses the new operator to create class objects. It's been done.

最后但并非最不重要的:写一个记录器如上所述相当棘手。 log4net的是一种流行的解决方案。 NLOG是一个更好的捕鼠器,那种感觉,而是作品的感觉就像一个Java接口dotnetty库。

Last but not least: writing a logger is fairly tricky as explained above. Log4net is a popular solution. NLog is a better mousetrap, a library that feels and works dotnetty instead of feeling like a Java port.

这篇关于类的析构问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆