关于C#Unmanaged object Disposing的一些最佳实践问题

时间:2015-02-19 04:38:57

标签: c# .net memory-management mono garbage-collection

我正在开发mono和.net应用程序。我对最佳实践有一些基本问题。

  1. 如果我需要创建一个非托管对象只是为了使用一次(可能会传递给方法或调用其中一种方法)并且以后不需要它,我应该分配它先变量变量然后使用它以便我可以处理它(或者可以在using()块中赋值变量)或者我应该使用类似new Class().Method()的变量,以便GC能够收集它?什么是最佳做法?

  2. 我是否需要处理只有方法的局部范围的对象,或者如果我处理属于该类属性的对象(全局),是否足够?

  3. 我有一个A类和一个B类.B的一个对象是在A类的某个方法M中创建的。这个对象(B类)有另一个方法M2,它调用A类中的第二个方法, M3。所以结构如下

    Class A
    {
      void M()
      {
       var b = new B();
       }
      public string M3()
      {
        return "OK";
       }
      }
      Class B
      {
        void M2()
        {
         Console.WriteLine(new A().M3();
         }
       }
    
  4. 这会创建一个循环引用来阻止GC收集这两个对象吗?

    良好的内存有效编程的其他一般原则是什么?

1 个答案:

答案 0 :(得分:2)

这个问题具有变得“过于宽泛”的重大风险,即StackOverflow的偏离主题。也就是说,一些简要回答:

  
      
  1. 如果我需要创建一个非托管对象只是为了使用一次(可能会传递给方法或调用其中一种方法)而以后不需要它......最佳实践是什么?
  2.   

使用任何非托管对象的最佳做法是将其包装在SafeHandle的实例中。当然,您必须处理的大多数常见非托管对象已经由.NET包装,可以在IDisposable的某些自定义实现中(例如StreamReader),也可以在更新的框架代码中,作为{ {1}}子类。

但是当你处理.NET不知道的你自己的非托管对象时,你会想要遵循.NET的例子并使用SafeHandle

  
      
  1. 我是否需要处理只有方法的局部范围的对象,或者如果我处理属于该类属性的对象(全局),是否足够?
  2.   

如果您创建了对象,并且尚未将其传递给其他代码以供其拥有,并且您不打算从该方法返回它,那么您需要将其处理掉。 do 需要处理仅在方法中引用的对象。

通常,您可以使用SafeHandle语句执行此操作。

  
      
  1. ...这会创建一个循环引用,停止GC收集这两个对象吗?
  2.   

忽略您的代码示例无法编译,也不包含任何引用循环......:)

与某些内存管理方案(例如引用计数)不同,.NET的垃圾回收根本没有任何循环引用问题。根据是否可以从 root 引用访问对象,确定该对象是否可收集。

表示两个无法引用的对象相互引用仍然无法从根引用中访问。

  

良好的内存有效编程的其他一般原则是什么?

这对于StackOverflow来说肯定太宽泛了。即使在.NET使用的基于GC的系统中,也有许多人可以关注的细节。基本系统消除了许多常见的编程错误,但它有自己的特殊行为,在某些情况下很难理解。

花一些时间浏览关于该主题的MSDN和网络文章将有助于您在.NET和一般情况下了解有关垃圾收集的更多信息。如果您有其他特定的问题,请随时在StackOverflow上发布。