问题描述
我发现了一般WeakReference的行为中没有想到的东西。
在我的测试中,在调用GC.Collect()之后释放了WeakReference的实例,但对于普通的WeakReference却没有:
单元测试用例
using NUnit.Framework;
using System;
namespace NUnitTestProject1
{
public class Tests
{
private const bool trackResurrection = false;
[SetUp]
public void Setup()
{
}
[TestCase(2,GCCollectionMode.Default,true)]
public void TestWeakReferenceWithObject(int generation,GCCollectionMode forced,bool blocking)
{
static WeakReference CreateWeakReference()
{
return new WeakReference(new object(),trackResurrection);
}
var x = CreateWeakReference();
Assert.IsTrue(x.IsAlive);
GC.Collect(generation,forced,blocking);
Assert.IsFalse(x.IsAlive);
}
[TestCase(2,GCCollectionMode.Forced,true)]
public void TestWeakReferenceWithString(int generation,bool blocking)
{
static WeakReference CreateWeakReference()
{
return new WeakReference(new string('a',100),true)]
public void TestGenericWeakReferenceWithObject(int generation,bool blocking)
{
static WeakReference<object> CreateWeakReference()
{
return new WeakReference<object>(new object(),trackResurrection);
}
var x = CreateWeakReference();
Assert.IsTrue(x.TryGetTarget(out var _));
GC.Collect(generation,blocking);
Assert.IsFalse(x.TryGetTarget(out var _));
}
[TestCase(2,true)]
public void TestGenericWeakReferenceWithString(int generation,bool blocking)
{
static WeakReference<string> CreateWeakReference()
{
return new WeakReference<string>(new string('a',blocking);
Assert.IsFalse(x.TryGetTarget(out var _));
}
}
}
我已经尝试过文档:
.NET Framework参考源代码:
但是我找不到导致行为不同的原因吗?
测试参数
可传递参数:
[TestCase(0,true)]
[TestCase(1,true)]
[TestCase(2,true)]
[TestCase(0,true)]
不可传递的参数:
//[TestCase(0,GCCollectionMode.Optimized,true)]
//[TestCase(1,true)]
//[TestCase(2,true)]
解决方法
仅注释掉第一个断言,我就通过了我的通用弱引用测试用例:
// Assert.IsTrue(x.TryGetTarget(out var _));
或者通过将调用移至WeakReference<T>.TryGetTarget(out T target)
来实现其自身功能:
using NUnit.Framework;
using System;
namespace NUnitTestProject1
{
public class Tests
{
private const bool trackResurrection = false;
[SetUp]
public void Setup()
{
}
[TestCase(2,GCCollectionMode.Forced,true)]
public void TestGenericWeakReferenceWithObject(int generation,GCCollectionMode forced,bool blocking)
{
static WeakReference<object> CreateWeakReference()
{
return new WeakReference<object>(new object(),trackResurrection);
}
static bool IsAlive(WeakReference<object> weakReference)
{
return weakReference.TryGetTarget(out var _);
}
var x = CreateWeakReference();
Assert.IsTrue(IsAlive(x));
GC.Collect(generation,forced,blocking);
Assert.IsFalse(IsAlive(x));
}
[TestCase(2,true)]
public void TestGenericWeakReferenceWithString(int generation,bool blocking)
{
static WeakReference<string> CreateWeakReference()
{
return new WeakReference<string>(new string('a',100),trackResurrection);
}
static bool IsAlive(WeakReference<string> weakReference)
{
return weakReference.TryGetTarget(out var _);
}
var x = CreateWeakReference();
Assert.IsTrue(IsAlive(x));
GC.Collect(generation,blocking);
Assert.IsFalse(IsAlive(x));
}
}
}
我的呼叫x.WeakReference(out var _)
中的丢弃变量必须保留对弱引用目标的引用。
添加变量作用域不会影响测试用例,但仍然失败:
{
x.WeakReference(out var _)
}