我正在尝试在事件处理过程中通过递归和修改来实现高效的调用列表。
我知道我可以使用委托和运算符+=
,-=
。我正在尝试一种替代方法,希望了解它与之比较。我不在乎多线程(使用Unity3d)。
主要问题:
考虑到唯一调用的方法是构造函数Subscribe
,Unsubscribe
和Send
,此代码正确吗?
其背后的想法:
count
变量仅调用在调用时列表中存在的处理程序using System;
using System.Collections.Generic;
/// <summary>
/// Invocation list which efficiently handles recursion and subscription/unsubscription during event handling.
/// </summary>
public class InvocationList<T> : List<Action<T>>
{
enum State { None, Running, RunningDirty }
static readonly Action<T> m_emptyAction = x => { };
State m_state = State.None;
public InvocationList()
{
}
public InvocationList(int capacity)
: base(capacity)
{
}
public void Subscribe(Action<T> handler)
{
Add(handler);
}
public bool Unsubscribe(Action<T> handler)
{
if (m_state == State.None)
{
// Not sending event, just remove handler
return Remove(handler);
}
else
{
// Sending event, replace handler by empty action
int index = IndexOf(handler);
if (index >= 0)
{
this[index] = m_emptyAction;
m_state = State.RunningDirty;
return true;
}
else
{
return false;
}
}
}
/// <summary>
/// Raises the event. Handles recursion and subscription/unsubscription during event handling.
/// Event is sent only to handlers present in invocation list at the moment of call.
/// </summary>
public void Send(T value)
{
if (m_state == State.None)
{
// Non-recursive invocation
try
{
m_state = State.Running;
ProcessHandlers(value);
}
finally
{
if (m_state == State.RunningDirty)
{
// Clean up empty handlers
RemoveAll(s => s == m_emptyAction);
}
m_state = State.None;
}
}
else
{
// Recursive invocation
ProcessHandlers(value);
}
}
private void ProcessHandlers(T value)
{
// Store count, this ignores handlers added during execution
int count = Count;
for (int i = 0; i < count; i++)
{
this[i](value);
}
}
}