使用 C# 事件递归

Recursion with C# Event

我正在调试 Microsoft prism 库中的一些代码。即一个名为 ModuleCatalog:

的 class
public class AppModuleCatalog : IAppModuleCatalog
{
    private readonly ModuleCatalogItemCollection _items;
    private bool _isLoaded;

    public Collection<IAppModuleCatalogItem> Items
    {
        get { return (Collection<IAppModuleCatalogItem>)this._items; }
    }

    public AppModuleCatalog()
    {
      this._items = new ModuleCatalogItemCollection();
      this._items.CollectionChanged += new NotifyCollectionChangedEventHandler(this.ItemsCollectionChanged);
    }

    public virtual void AddModule(AppModuleInfo moduleInfo)
    {
        Argument.IsNotNull("moduleInfo", moduleInfo);

        this.Items.Add(moduleInfo);
    }

    public AppModuleCatalog AddModule(string moduleName, string moduleType, string refValue, InitializationMode initializationMode, params string[] dependsOn)
    {
        Argument.IsNotNull("ModuleName", moduleName);
        Argument.IsNotNull("moduleType", moduleType);

        AppModuleInfo moduleInfo = new AppModuleInfo(moduleName, moduleType);

        moduleInfo.DependsOn.AddRange(dependsOn);
        moduleInfo.InitializationMode = initializationMode;
        moduleInfo.Ref = refValue;
        this.Items.Add(moduleInfo);

        return this;
    }

    private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (!this.Validated)
            return;
        this.EnsureCatalogValidated();
    }
    .
    .
    .

    private class ModuleCatalogItemCollection : Collection<IAppModuleCatalogItem>, INotifyCollectionChanged
    {
        public event NotifyCollectionChangedEventHandler CollectionChanged;

        protected override void InsertItem(int index, IAppModuleCatalogItem item)
        {
           InsertItem(index,item); 
           this.OnNotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
        }

        protected void OnNotifyCollectionChanged(NotifyCollectionChangedEventArgs eventArgs)
        {
            if (this.CollectionChanged == null) return;
            this.CollectionChanged(this, eventArgs);
        }
    }
}

初始化此 class 时,将调用 AddModule 方法将 ModuleInfo 添加到 Items 属性。我注意到的是,然后调用私有 class 并在 InsertItem 方法中重复进行递归调用,这当然会导致 OverFlow 异常。请注意 getter 来自 Items 属性 returns _items

你能解释一下为什么会发生递归吗?

根据 original source codeModuleCatalogItemCollection.InsertItem(int, IModuleCatalogItem) 方法实现如下所示:

protected override void InsertItem(int index, IModuleCatalogItem item)
{
    base.InsertItem(index, item);

    this.OnNotifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
}

注意 base.InsertItem(index, item) 方法调用。这将从 Collection<IModuleCatalogItem> class 而不是 this.InsertItem() 调用基本方法实现。所以这里没有递归调用。