C# 字典trygetvalue null private Dictionary events=new Dictionary(); 内部包GetEventList(),其中T:class { 类型=类型(T); b袋; if(events.TryGetValue(类型,输出b)) { 返回b作为包; } 否则{ b=新袋()作为袋; 事件[类型]=b; 返回b作为包; } } 内部无效添加事件(T ev),其中T:类别、事件 { 类型=类型(T); b袋; if(events.TryGetValue(类型,输出b)) { b、 添加(ev);//

C# 字典trygetvalue null private Dictionary events=new Dictionary(); 内部包GetEventList(),其中T:class { 类型=类型(T); b袋; if(events.TryGetValue(类型,输出b)) { 返回b作为包; } 否则{ b=新袋()作为袋; 事件[类型]=b; 返回b作为包; } } 内部无效添加事件(T ev),其中T:类别、事件 { 类型=类型(T); b袋; if(events.TryGetValue(类型,输出b)) { b、 添加(ev);//,c#,dictionary,nullreferenceexception,C#,Dictionary,Nullreferenceexception,可能的罪魁祸首是这一行: private Dictionary<Type, Bag<Event>> events = new Dictionary<Type, Bag<Event>>(); internal Bag<T> GetEventList<T>() where T:class { Type type = typeof(T); Bag<Event> b; if (events

可能的罪魁祸首是这一行:

 private Dictionary<Type, Bag<Event>> events = new Dictionary<Type, Bag<Event>>();

 internal Bag<T> GetEventList<T>() where T:class
 {
    Type type = typeof(T);
    Bag<Event> b;
    if (events.TryGetValue(type, out b))
    {
        return b as Bag<T>;
    }
    else {
        b = new Bag<T>() as Bag<Event>;
        events[type] = b;
        return b as Bag<T>;
    }
}

internal void AddEvent<T>(T ev) where T:class,Event
{
    Type type = typeof(T);
    Bag<Event> b;
    if (events.TryGetValue(type, out b))
    {
        b.Add(ev); // <= NullReferenceException, b is null
    }
    else {
        b = new Bag<T>() as Bag<Event>;
        events.Add(type, b);
        b.Add(ev);
    }
}
b=新行李(),作为行李;
as
转换可能失败,这将
null
分配给
b

我的猜测是,您正在使用
Event
的子类作为
T
的类型,并且由于
Bag
在类型参数上是不协变的(我假设它是一个类,所以它不可能是),强制转换失败,最终导致
b
null


更新:根据下面的评论,问题确实是
的演员阵容。要解决问题,只需创建一个
新包()
,无需演员阵容。

可能的罪魁祸首是这一行:

 private Dictionary<Type, Bag<Event>> events = new Dictionary<Type, Bag<Event>>();

 internal Bag<T> GetEventList<T>() where T:class
 {
    Type type = typeof(T);
    Bag<Event> b;
    if (events.TryGetValue(type, out b))
    {
        return b as Bag<T>;
    }
    else {
        b = new Bag<T>() as Bag<Event>;
        events[type] = b;
        return b as Bag<T>;
    }
}

internal void AddEvent<T>(T ev) where T:class,Event
{
    Type type = typeof(T);
    Bag<Event> b;
    if (events.TryGetValue(type, out b))
    {
        b.Add(ev); // <= NullReferenceException, b is null
    }
    else {
        b = new Bag<T>() as Bag<Event>;
        events.Add(type, b);
        b.Add(ev);
    }
}
b=新行李(),作为行李;
as
转换可能失败,这将
null
分配给
b

我的猜测是,您正在使用
Event
的子类作为
T
的类型,并且由于
Bag
在类型参数上是不协变的(我假设它是一个类,所以它不可能是),强制转换失败,最终导致
b
null


更新:根据下面的评论,问题确实是
as
强制转换。要解决问题,只需创建一个
新包()
,无需强制转换。

某个空值与密钥类型关联


在抛出
NullReferenceException
之前,在调试器中逐步检查代码并检查字典的状态。

在某个地方,null与键类型相关联


在抛出
NullReferenceException
之前,在调试器中逐步检查代码,并检查字典的状态。

NullReferenceException
Bag
无法强制转换到
Bag
时抛出


如果您将签名更改为
内部无效添加事件(事件ev),其中T:class
异常将解除
NullReferenceException
Bag
无法转换为
Bag
时抛出


如果您将签名更改为
internal void AddEvent(Event ev),其中T:class
异常将被解除

,因为您的
Bag b;
在字典中为空?您确定
b=new Bag()as Bag;
不是
null
?您能告诉我们您正在调用的代码,以及围绕
事件的任何类型层次结构吗?因为您的
Bag b;
在字典中是null吗?您确定
b=new Bag()因为Bag;
不是
null
?您能告诉我们您正在调用的代码,以及围绕
事件的任何类型层次结构吗?
?它不会在最后一个b.Add(ev)中引发另一个NullReferenceException吗;如果是这样的话?@LimoWanKenobi我只能推测,因为我们还没有看到调用代码,但我猜最初的调用使用
Event
作为泛型参数,但随后的调用没有。另一种可能是
GetEventList()
调用首先发生,但在字典中找不到该类型,因此该方法中的
as
强制转换将导致null,导致下一次为给定类型调用add时出现null ref。无论实际顺序如何,很可能是问题出在
as
强制转换。在第一个方法中,
GetEventList
,他还使用
as
操作符,他还添加到
字典中
那里!他只是使用索引器的setter来执行。而且该方法甚至不将其
t
约束为
事件
。Alejandro,永远不要使用
as
操作符,除非您同意结果可能是
null
。如果您不准备处理
null
,请使用“硬”强制转换。在您的代码中,
T
Event
之间有什么关系?-好的,让我们看看。在我的代码中,“Event”是一个接口,而T实现了该接口。-我添加了一些断点,在AddEvent()之前没有调用GetEventList()-我将删除“as”强制转换,看看会发生什么。谢谢。@dlev调用代码:(CellsChangedEvent实现事件)
world.SystemManager.AddEvent(新CellsChangedEvent(实体));
它不会在最后一个b.Add(ev)中引发另一个NullReferenceException吗;如果是这样的话?@LimoWanKenobi我只能推测,因为我们还没有看到调用代码,但我猜最初的调用使用
Event
作为泛型参数,但随后的调用没有。另一种可能是
GetEventList()
调用首先发生,但在字典中找不到该类型,因此该方法中的
as
强制转换将导致null,导致下一次为给定类型调用add时出现null ref。无论实际顺序如何,很可能是问题出在
as
强制转换。在第一个方法中,
GetEventList
,他还使用
as
操作符,他还添加到
字典中
那里!他只是使用索引器的setter来执行。而且该方法甚至不将其
t
约束为
事件
。Alejandro,永远不要使用
as
操作符,除非您同意结果可能是
null
。如果您不准备处理
null
,请使用“硬”强制转换。在您的代码中,
T
Event
之间有什么关系?-好的,让我看看。在我的代码中,“Event”是一个接口,而T实现了该接口。-我补充道