为什么这个lambda表达式包含闭包?

时间:2016-10-02 20:08:29

标签: c# lambda closures

我正在使用UWP(通用Windows 10应用程序)社区工具包中的一个名为WeakEventListener的源代码(源代码可用here)来订阅事件,同时允许侦听器由垃圾收集器完成,因为这在我的项目过去一直是内存泄漏的来源。绝对关键的一点是分配给OnEventAction和OnDetachAction的委托不得包含闭包(即对监听器的强引用,或this)。但是看起来我总是在关闭,即使我不在委托中使用this(通常是lambda表达式)。下面是一个示例lambda表达式(在TransitMap类的构造函数中,它有一个名为AddIns_CollectionChanged的私有方法):

addInsListener.OnEventAction = (map, obj, e) => map.AddIns_CollectionChanged(obj, e);

但是当我在WeakEventListener类中强制执行没有闭包的委托时:

private Action<TInstance, TSource, TEventArgs> _OnEventAction;
    /// <summary>
    /// Gets or sets the method to call when the event fires.
    /// </summary>
    public Action<TInstance, TSource, TEventArgs> OnEventAction
    {
        get { return _OnEventAction; }
        set
        {
            if (value?.Target != null)
                throw new Exception("Any delegate passed to a WeakEventListener must be static, otherwise a memory leak exists.");
            _OnEventAction = value;
        }
    }

问题是委托总是有一个非空的Target,即使它本身没有引用this!有谁知道为什么会这样?

更新:以下是我班上的一些相关代码,这是证明问题的最低要求。

public sealed class TransitMap : UserControl
{
    private ObservableCollection<TransitMapAddInBase> AddIns = new ObservableCollection<TransitMapAddInBase>();
    public TransitMap()
    {
        WeakEventListener<TransitMap, object, NotifyCollectionChangedEventArgs> addInsListener = new WeakEventListener<TransitMap, object, NotifyCollectionChangedEventArgs>(this);
        //Problem line. Lambda expression holds up a strong reference to 'this' (in its Target) despite using a parameter for the listener instead of this.
        addInsListener.OnEventAction = (map, obj, e) => map.AddIns_CollectionChanged(obj, e);
        AddIns.CollectionChanged += addInsListener.OnEvent;
    }


    private void AddIns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        //Do something...
    }
}

0 个答案:

没有答案