请考虑以下代码:
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
#nullable enable
namespace ConsoleApp1
{
class Program
{
static void Main()
{
var list = makeList();
var weakRef = new WeakReference(list[0]);
list[0] = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(weakRef.IsAlive);
}
[MethodImpl(MethodImplOptions.NoInlining)]
static List<int[]?> makeList()
{
return new List<int[]?> { new int[2] };
}
}
}
- 在 .Net Framework 4.8 的 release 或 debug 版本中,该代码会打印
False
。 - 在 .Net Core 3.1 的 release 或 debug 版本中,该代码会打印
True
。
是什么导致了这种行为上的差异?(这导致我们的部分单元测试失败。)
注意:我将列表初始化放入makeList()
,并关闭了内联以尝试使 .Net Core 版本与 .Net Framework 版本的工作方式相同,但无济于事。
[编辑] 正如 Hans 指出的,添加循环可以解决这个问题。
以下代码会打印 False
:
var list = makeList();
var weakRef = new WeakReference(list[0]);
list[0] = null;
for (int i = 0; i < 1; ++i)
GC.Collect();
Console.WriteLine(weakRef.IsAlive);
但是这将打印出True
:
var list = makeList();
var weakRef = new WeakReference(list[0]);
list[0] = null;
GC.Collect();
GC.Collect();
GC.Collect();
GC.Collect();
// Doesn't seem to matter how many GC.Collect() calls you do.
Console.WriteLine(weakRef.IsAlive);
这一定是某种奇怪的Jitter问题...
GC.Collect()
,但是并没有解决问题 - 但是一个简单的循环就可以。嗯。 - Matthew Watson