Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在静态字段中引用自身的类可以被垃圾收集吗?_C#_Static_Garbage Collection_Private - Fatal编程技术网

C# 在静态字段中引用自身的类可以被垃圾收集吗?

C# 在静态字段中引用自身的类可以被垃圾收集吗?,c#,static,garbage-collection,private,C#,Static,Garbage Collection,Private,假设MyClass的实例没有以任何其他方式扎根,这里的私有静态引用会阻止它被垃圾收集吗?您发布的类不会被垃圾收集。您可以通过给它一个带有控制台输出的终结器来测试它: public class MyClass { private static MyClass heldInstance; public MyClass() { heldInstance = this; } } 输出将是: public class MyClass { private static MyC

假设MyClass的实例没有以任何其他方式扎根,这里的私有静态引用会阻止它被垃圾收集吗?

您发布的类不会被垃圾收集。您可以通过给它一个带有控制台输出的终结器来测试它:

public class MyClass {
  private static MyClass heldInstance;

  public MyClass() {
    heldInstance = this;
  }
}
输出将是:

public class MyClass
{
    private static MyClass heldInstance;
    public MyClass()
    {
        heldInstance = this;
    }
    ~MyClass()
    {
        Console.WriteLine("Finalizer called");
    }
}
class Program
{
    static void Main(string[] args)
    {
        var x = new MyClass(); // object created

        x = null; // object may be eliglible for garbage collection now

        // theoretically, a GC could happen here, but probably not, with this little memory used
        System.Threading.Thread.Sleep(5000);

        // so we force a GC. Now all eligible objects will definitely be collected
        GC.Collect(2,GCCollectionMode.Forced);

        //however their finalizers will execute in a separate thread, so we wait for them to finish
        GC.WaitForPendingFinalizers();

        System.Threading.Thread.Sleep(5000);
        Console.WriteLine("END");

    }
}
这意味着该类仅在应用程序的最终拆卸时收集,而不是在常规垃圾收集期间收集

如果像这样创建此类的多个实例:

END
Finalizer called
然后,除了最近的一个,所有的都将被垃圾收集

你会得到

var x = new MyClass();
x = new MyClass();
x = new MyClass();
x = new MyClass();

垃圾收集器确定哪些对象是可访问的,并将收集那些不可访问的对象。要确定对象是否可访问,收集器将从所谓的根开始。根中有当前在求值堆栈上的内容,也有静态字段。收集器将跟随对对象的引用,从根到任何对象,从这样的对象到任何其他对象,依此类推。以这种方式访问的每个对象都是可访问的,因此将保持活动状态


在您的例子中,静态字段是垃圾收集器的根之一,因此它永远不会收集该字段(间接)引用的任何对象。但是,如果将该字段设置为
null
,则该字段将不再引用该实例,并且该实例可能会被收集。

编辑的可能重复:简而言之,不,我认为不会。例如,在您发布的代码中,公共构造函数没有理由不具有
if(heldInstance==null)
除此之外,GC一旦确定不再可访问时,将最终收集仅保留的引用从自身到自身的实例。是的,它们在AppDomain卸载之前被收集。除非类有终结器,否则这是无关紧要的。类的静态字段引用同一类的实例这一事实是无关的。静态场是根;它们将使您放入其中的任何内容保持活动状态,无论其类型如何。请注意,这是正确的,因为
heldInstance
是静态的。
MyClass
的实例有一个对自身的引用,这一事实没有什么特别之处。所以,是的,“引用自身的类”可以被垃圾收集。但是,示例中的类不能。
Finalizer called
Finalizer called
Finalizer called
END
Finalizer called