我只是在思考一些任务,并对一些基本概念产生了误解。这段代码
namespace Game {
public static class EventSystem {
public class EventBase { }
public interface IEventListener<in TEvent> where TEvent : EventBase {
void OnEvent(TEvent ev);
}
private static Dictionary<Type, List<IEventListener<EventBase>>> _subscriptions = new();
public static void AddListener<TEvent>(IEventListener<TEvent> listener) where TEvent : EventBase {
if (!_subscriptions.ContainsKey(typeof(TEvent))) {
_subscriptions.Add(typeof(TEvent), new());
}
var list = _subscriptions[typeof(TEvent)];
list.Add(listener);
}
public static void RemoveListener<TEvent>(IEventListener<TEvent> listener) where TEvent : EventBase {
if (_subscriptions.ContainsKey(typeof(TEvent))) {
var list = _subscriptions[typeof(TEvent)];
list.Remove(listener);
}
}
在带有
list.Add(listener)
和 list.Remove(listener)
的行给我以下错误:
> Argument 1: cannot convert from
> 'Game.EventSystem.IEventListener<TEvent>' to
> 'Game.EventSystem.IEventListener<Game.EventSystem.EventBase>'CS1503
我正在尝试找出原因以及如何解决这个问题。 Cast (
list.Add((IEventListener<EventBase>)listener);
) 在运行时给我一个异常:System.InvalidCastException:指定的强制转换无效。
所以,如果我正确理解了这种情况,
IEventListener<TEvent>
对于EventBase
来说是不变的,尽管TEvent
实际上是EventBase
。我不明白的是‘为什么’?
PS。我知道可能存在内存泄漏,我们不讨论这个) - 只是想理解泛型类型参数有什么问题
关于文章创建变体通用接口(C#),你做不到。
作为可能的解决方案,您可以执行以下操作:
private static Dictionary<Type, object> _subscriptions = new();
public static void AddListener<TEvent>(IEventListener<TEvent> listener) where TEvent : EventBase {
if (!_subscriptions.TryGetValue(typeof(TEvent), out object? objList)) {
Type listType = typeof(List<>).MakeGenericType(typeof(IEventListener<TEvent>));
objList = Activator.CreateInstance(listType);
_subscriptions.Add(typeof(TEvent), objList);
}
var list = (List<IEventListener<TEvent>>)objList;
list.Add(listener);
}
public static void RemoveListener<TEvent>(IEventListener<TEvent> listener) where TEvent : EventBase {
if (_subscriptions.ContainsKey(typeof(TEvent))) {
var list = (List<IEventListener<TEvent>>)_subscriptions[typeof(TEvent)];
list.Remove(listener);
}
}