ang*_*son 8 .net c# delegates garbage-collection
我有一个持有代表的课程,以便稍后懒洋洋地评估一些事情.
一旦我评估了它,通过调用委托,我清除了对委托的引用,希望它有资格收集.毕竟,如果将它构造为匿名方法,它可能会保留一个局部变量的世界.
我尝试构建一个单元测试来验证这一点,但它似乎没有按照我计划的方式运行,而是看起来我的假设WeakReference(我在这里用于测试目的),或者其他一些假设,都没有.拿水.
看看这段代码,你可以在LINQPad中运行它
void Main()
{
WeakReference wr;
Lazy<int> l;
CreateTestData(out wr, out l);
wr.IsAlive.Dump(); // should be alive here
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
wr.IsAlive.Dump(); // and alive here as well
l.Value.Dump(); // but now we clear the reference
GC.Collect(); // so one of these should collect it
GC.WaitForPendingFinalizers();
GC.Collect();
wr.IsAlive.Dump(); // and then it should be gone here
GC.KeepAlive(l);
}
void CreateTestData(out WeakReference wr, out Lazy<int> l)
{
Func<int> f = () => 10;
wr = new WeakReference(f);
l = new Lazy<int>(f);
}
public class Lazy<T>
{
private Func<T> _GetValue;
private T _Value;
public Lazy(Func<T> getValue)
{
_GetValue = getValue;
}
public T Value
{
get
{
if (_GetValue != null)
{
_Value = _GetValue();
_GetValue = null;
}
return _Value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我假设:
WeakReference和Lazy<T>对象之外,应该没有任何东西保留委托Lazy<T>对象放弃对委托的引用,这将减少对仅WeakReference持有的对象的引用WeakReferenceWeakReference会表明该对象不再存在因此预计代码的输出(带注释):
true // not gc'ed after construction
true // not gc'ed after full GC, still beind held by Lazy<T>
10 // value from calling delegate
false // but is now gc'ed, Lazy<T> no longer has a reference to it
Run Code Online (Sandbox Code Playgroud)
但相反输出是:
true
true
10
true
Run Code Online (Sandbox Code Playgroud)
任何人都可以了解我在这里缺少的东西吗?
"问题"是编译器注意到它可以永远重用单个委托实例.它不捕获任何上下文,甚至不捕获隐式this引用.所以这:
void CreateTestData(out WeakReference wr, out Lazy<int> l)
{
Func<int> f = () => 10;
...
}
Run Code Online (Sandbox Code Playgroud)
变成了这样的东西:
static Func<int> hiddenDelegate;
static int HiddenMethod()
{
return 10;
}
void CreateTestData(out WeakReference wr, out Lazy<int> l)
{
if (hiddenDelegate == null)
{
hiddenDelegate = HiddenMethod;
}
Func<int> f = hiddenDelegate;
...
}
Run Code Online (Sandbox Code Playgroud)
查看ildasm(或没有打开优化的Reflector)中的代码,看看究竟发生了什么.
| 归档时间: |
|
| 查看次数: |
503 次 |
| 最近记录: |