C#析构函数的正确使用方法

3

我一直在研究如何为我编写的类实现析构函数,但我不确定如何释放内存,或者是否会由垃圾回收机制处理。

class AutomatedTest
{
   public bool testComplete = false;
   public bool testStopRequest = false;

   public List<Command> commandList = new List<Command>();

   private bool loggingEnabled = false;
   ...


   public AutomatedTest(TestList testToCreate)
   {
       // Create a list of Command objects and add them to the list
   }
}  

这个类的使用方法:

for(int numTests = 0; numTests < 20; numTests++)
{
    AutomatedTest test1 = new AutomatedTest(TestList._1DayTest);
    RunAutoTest(test1);

    AutomatedTest test2 = new AutomatedTest(TestList._2DayTest);
    RunAutoTest(test2);

    AutomatedTest test3 = new AutomatedTest(TestList._3DayTest);
    RunAutoTest(test3);

    AutomatedTest test4 = new AutomatedTest(TestList._4DayTest);
    RunAutoTest(test4);
}  

所以创建并运行了4个对象,这样做20次。
我的问题是如何正确的释放/销毁这些对象?我不想假设这些对象是由垃圾回收机制处理的,但我对实现析构函数很陌生。


可能是析构函数 vs IDisposable?的重复问题。 - BrokenGlass
7个回答

2
只要您不使用任何实现IDisposable的对象,就不需要手动处理释放或销毁。

1
当您的对象被垃圾回收时,类的析构函数会被调用。在像C#这样的托管编程语言中,您无法控制垃圾回收器何时运行并执行析构函数。当CLR(公共语言运行时)看到对象不再被引用或在程序后面不再使用时,它会负责垃圾回收。在您的示例中,考虑代码:

AutomatedTest test1 = new AutomatedTest(TestList._1DayTest);
RunAutoTest(test1);

执行RunAutoTest(test1)后,“test1”引用变量不再使用,并将可供垃圾回收。但实际的垃圾回收过程可能不会立即运行,也没有办法确保它在特定时间运行。如果在AutomatedTest类中使用资源(如打开FileStream等),则需要在使用该类的对象完成后释放这些资源。可以通过以下方式使您的类实现IDisposable接口来完成此操作。
class AutomatedTest:IDisposable
    {
        public void Dispose()
        {
            //free up any resources
        }
    }

一旦您的类实现了IDisposable接口,您可以通过将其创建包装在“using”块中来使用它。

 for (int numTests = 0; numTests < 20; numTests++)
        {
            using (AutomatedTest test1 = new AutomatedTest(TestList._1DayTest))
            {
                RunAutoTest(test1);
            }
            //as soon as code exits the 'using' block the dispose method on test1 would be called
            //this is something you cannot guarantee when implementing a destructor

            using (AutomatedTest test2 = new AutomatedTest(TestList._2DayTest))
            {
                RunAutoTest(test2);
            }
            //dispose on test2 will be called here

            ///rest of code
        }  

顺便提一下,在C#中可以使用~来实现析构函数。但是,实现IDisposable接口的方法比创建析构函数更可取。

  class AutomatedTest
    {

        ~AutomatedTest()
        {
            //code will run only on garbage collection
        }
    }

1

您将无法控制这些对象何时被垃圾回收。正如Henk Holterman所提到的,您可能需要考虑实现IDisposable或使用IDisposable模式。如果不需要这样做,我不会担心使用.Dispose()或一个终结器~AutomatedTest()

假设这些测试方法可能需要一段时间,您可以在使用完后说test1 = null;,以让.NET知道此对象引用不再使用,否则一旦超出范围,GC将清理事物。


0

你最好的选择是使用详细介绍在这里的IDisposable模式。但正如其他人指出的那样,只有当你的对象持有一些昂贵的资源时,比如文件句柄、流、数据库对象等,才需要使用该模式。其他所有东西都将由GC自动回收。相信它。


0

我认为一个公平的规则是:“如果你的任何对象处理非托管资源或实现IDisposable,则需要处理它们。” 我在您发布的代码中没有看到任何非托管资源,所以您可能不需要担心。但是,显然有一些我们看不到的代码,所以我不能确定。

请阅读MSDN文章以了解正确处理的说明。


0

“析构函数”或通常称为Finalizer,只有在对象被垃圾回收时才会被调用。

因此,如果您有需要释放的资源,最好实现IDisposable


0

处理昂贵对象的一种方法是实现IDisposable接口并实现Dispose和Finalize方法。当您的类对非托管代码具有依赖关系并负责清理它们时,这是推荐的模式。详细信息请点击此处


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接