gpt4 book ai didi

c# - 在收集实例之前,如何将 WeakReference 保存到实例的方法?

转载 作者:太空宇宙 更新时间:2023-11-03 18:53:27 25 4
gpt4 key购买 nike

class Program
{
static void Main(string[] args)
{
var inst = new SomeClass();
var weakRef = new WeakReference<Action>(inst.DoSomething);
GC.Collect();
Console.WriteLine($"inst is alive = {inst != null} : weakRef.Target is alive = {weakRef.TryGetTarget(out Action callback)}");
Console.ReadLine();
}
}

public class SomeClass
{
public void DoSomething() { }
}

输出显示 inst不为空,但引用 WeakReference<Action>指向是。我预计这是因为创建了一个指向实例方法的新 Action,而不是存储对实例方法本身的引用。

在实例尚未被垃圾回收期间,如何保持对对象实例方法的弱引用?

最佳答案

如果你需要 ActionSomeClass 之前不会收集实例例如,那么您需要添加来自 SomeClass 的引用实例到 Action实例。可以是SomeClass的实例字段指向Action实例,但如果你不能改变 SomeClass定义,比你可以使用 ConditionalWeakTable<TKey,TValue> 动态附加字段的类。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default)]
public class SomeClass {
public void DoSomething() { }
}
public static class DelegateKeeper {
private static ConditionalWeakTable<object, List<Delegate>> cwt = new ConditionalWeakTable<object, List<Delegate>>();
public static void KeepAlive(Delegate d) => cwt.GetOrCreateValue(d?.Target ?? throw new ArgumentNullException(nameof(d))).Add(d);
}
static class Program {
static void Main() {
SomeClass inst = new SomeClass();
Action a1 = inst.DoSomething;
DelegateKeeper.KeepAlive(a1);
Action a2 = inst.DoSomething;
WeakReference<SomeClass> winst = new WeakReference<SomeClass>(inst);
WeakReference<Action> wa1 = new WeakReference<Action>(a1);
WeakReference<Action> wa2 = new WeakReference<Action>(a2);
GC.Collect();
Console.WriteLine($"{winst.TryGetTarget(out _),5}:{wa1.TryGetTarget(out _),5}:{wa2.TryGetTarget(out _),5}");
GC.KeepAlive(a1);
GC.KeepAlive(a2);
GC.Collect();
Console.WriteLine($"{winst.TryGetTarget(out _),5}:{wa1.TryGetTarget(out _),5}:{wa2.TryGetTarget(out _),5}");
GC.KeepAlive(inst);
GC.Collect();
Console.WriteLine($"{winst.TryGetTarget(out _),5}:{wa1.TryGetTarget(out _),5}:{wa2.TryGetTarget(out _),5}");
}
}

输出:

 True: True: True
True: True:False
False:False:False

tio.run

DelegateKeeper我使用的类 List<Delegate>作为依赖对象类型,因此您可以为每个类实例保留多个委托(delegate)。我用 Delegate.Target 作为表的键,所以你不需要单独传递实例。这不适用于匿名方法,因为它们可能有编译器在 Target 中生成闭包类属性(property)。 GetOrCreateValue获取绑定(bind)到键的值或使用默认构造函数创建新值并自动将其添加到表中。

关于c# - 在收集实例之前,如何将 WeakReference<Action> 保存到实例的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51456875/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com