我在下面发布了代码,我无法弄清楚为什么这不可能。我收到一个编译器错误:无法从System.Action转换为System.Action。
实现这样的东西的正确方法是什么?
我来自Java背景,我正在尝试使用通配符泛型来完成通常可以做的事情。但是我不明白为什么当T被限制为扩展Event时会出现此错误。
我省略了确保列表实际退出的代码。
public class EventBus : ScriptableObject {
public Event[] events;
private Dictionary<Type, List<Action<Event>>> listeners = new Dictionary<Type, List<Action<Event>>>();
public void Register<T>(Action<T> function) where T : Event {
listeners[typeof(T)].Add(function);
}
}
// The event class
public abstract class Event : ScriptableObject {
public abstract void Raise();
}
更新
基本,我正在尝试执行以下操作:
eventBus.register<CutomEvent>(MyFunction);
其中
public void MyFunction(CustomEvent event);
这样,我可以使用通用参数指定要监听的事件。字典仅包含要侦听特定事件类型的每个函数的列表
更新: 这就是我在Java中拥有的东西
public class EventBus {
public Map<Class<?>, List<SomeInterface<?>>> listeners = new HashMap<>();
public<T extends Event> void register(SomeInterface<T> func, Class<T> clazz) {
listeners.get(clazz).add(func);
}
public interface SomeInterface<T extends Event> {
void process(T event);
}
public static void main(String[] args) {
new EventBus().register(event -> {
// Do something with my event
event.someFunc();
}, MyEvent.class);
}
private static class MyEvent extends Event {
public void someFunc(){}
}
}
答案 0 :(得分:2)
即使Action<T>
也不能将Action<Event>
强制转换为T : Event
,但是可以将任何Action<T>
强制转换为Delegate
,然后冒着以下风险:运行时错误,将Delegate
转换回Action<T>
。但是,由于字典的键是typeof(T)
,因此可以避免发生运行时错误的风险。
尝试以下代码:
public class EventBus : ScriptableObject
{
public Event[] events;
private Dictionary<Type, List<Delegate>> listeners
= new Dictionary<Type, List<Delegate>>();
public void Register<T>(Action<T> function) where T : Event
{
listeners[typeof(T)].Add(function);
}
public Action<T>[] Retrieve<T>() where T : Event
{
return listeners[typeof(T)].Cast<Action<T>>().ToArray();
}
}