我刚刚在Visual Studio 2013 Update 4中发现了一个非常奇怪的行为。请考虑以下xunit.net测试:
[Fact]
public void TestTargetMustNotHoldAReferenceToItemsAfterCallingClear()
{
var item = new MarkedType();
var weakReferenceToItem = new WeakReference<MarkedType>(item);
var testTarget = new ListBuilder<MarkedType>().WithItems(item)
.Build();
testTarget.Clear();
item = null;
GC.Collect();
MarkedType retrievedItem = null;
Assert.False(weakReferenceToItem.TryGetTarget(out retrievedItem));
Assert.Null(retrievedItem);
}
public class MarkedType { }
在其中,我想检查我自己的List<T>
实现在我调用Clear
之后没有对堆上的对象的引用。因此,在调用item
之后,我将null
设置为Clear
,并让垃圾收集器运行,以便它可以释放MarkedType
实例。之后我用弱引用检查实例是否真的消失了。
这是奇怪的事情:此测试未通过xunit.net v2.0.0预发行版在VS 2013 Update 4中的调试模式下传递,因为WeakReference.TryGetTarget
返回true
。 但是,如果我切换到发布模式,则此测试通过。我还在VS 2015 CTP6中运行了此测试,并在其中传递了两个配置,即调试和发布。
然后我创建了两个内存转储(一个在垃圾收集器运行之前,一个之后)以找出哪个对象在内存中保留item
并且我找到了一个未在我的测试中列出的对象数组:
我的实际问题是:这个对象数组来自哪里?为什么它不在发布模式(或VS 2015)中出现?我可以以某种方式禁用或绕过它吗?
如果您想使用源代码,可以在github上使用(请使用FailingReferenceTest分支):https://github.com/feO2x/BeginningTdd