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 次。
我的问题是我应该如何正确处置/销毁这些对象?我不想假设这些是垃圾收集的,但我是实施析构函数的新手。

4

7 回答 7

2

只要您不使用任何实现 IDisposable 的对象,您就不必手动处置或销毁。

于 2012-04-27T19:28:32.787 回答
1

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

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

于 2012-04-27T19:28:50.993 回答
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,你可以通过将它的创建包装在一个“使用”块中来使用它

 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
        }
    }
于 2012-04-27T19:57:28.927 回答
0

您最好的选择是此处详述的 IDisposable 模式。但正如其他人指出的那样,只有当您的对象持有一些昂贵的资源(如文件句柄、流、DB 对象等)时,这才是必要的。其他一切都将由 GC 收集。相信它。

于 2012-04-27T19:28:49.967 回答
0

我相信对此的公平规则是“如果您的任何对象处理非托管资源或实现 IDisposable,则需要处置它们。” 我在您发布的代码中没有看到任何不受管理的内容,因此您可能无需担心。但是,显然有些代码我们看不到,所以我不能确定。

请阅读此MSDN 文章以获取有关正确处理的说明。

于 2012-04-27T19:29:20.683 回答
0

在对象被垃圾回收之前, “析构函数”或Finalizer通常称为的“析构函数”不会被调用。

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

于 2012-04-27T19:29:20.933 回答
0

处理昂贵对象的处置的方法之一是实现 IDisposable 接口并实现 Dispose 和 Finalize 方法。当您的类依赖于非托管代码并负责清理它们时,这是推荐的模式。更多细节在这里

于 2012-04-27T19:29:53.763 回答