为什么还有对这个字符串的引用?

Why is there still a reference onto this string?

我在摆弄 WeakReferenceWeakReference<T>。它们只适用于 classes(显然,reference)所以我用字符串做了一个例子(字符串是 .Net 中的 class)。

当我 运行 下面的代码片段时,它没有提供我预期的结果,意思是 WeakReference 仍然包含字符串。

  string please = "wat";
  WeakReference<string> test = new WeakReference<string>(please);
  string testresult;
  please = null;
  GC.Collect();
  bool worked = test.TryGetTarget(out testresult);
  Console.WriteLine("it is " + worked);

result: "it is true"

现在,当我围绕字符串创建一个简单的包装器 class 时:

class TestWeakStuff
{
  public string Test { get; set; }
}

并使用它代替字符串,做了 return 我的预期结果:

  TestWeakStuff testclass = new TestWeakStuff() { Test = "wat" };
  WeakReference<TestWeakStuff> test2 = new WeakReference<TestWeakStuff>(testclass);
  TestWeakStuff testresult2;
  testclass = null;
  GC.Collect();
  bool worked2 = test2.TryGetTarget(out testresult2);
  Console.WriteLine("2nd time is " + worked2);

Result: "2nd time is false"

我对非泛型 WeakReference class 进行了同样的尝试,结果是一样的。

为什么字符串没有被垃圾收集器回收?

(GC.Collect() 确实声明了所有世代,外部 GC 调用带有 -1(所有世代))

字符串文字不适合测试 GC 行为。字符串文字被添加到 CLR 上的 intern pool。这导致每个不同的字符串文字只有一个对象驻留在内存中。这是一个优化。实习生池中的字符串会被永远引用并且永远不会被收集。

字符串不是普通的class。它们是运行时的固有特性。

您应该能够使用 new string('x', 10) 对其进行测试,它每次都会创建一个新对象。保证如此。有时,这用于在将字符串发布到其他代码之前使用不安全代码写入字符串。也可以与本机代码一起使用。

最好完全放弃测试字符串。您获得的结果不是特别有趣或保证在运行时更改时保持稳定。

您可以使用 new object() 进行测试,这是最简单的测试方法。