我想在枚举存储中使用我希望在EventHandler中使用的密钥。
public enum EventKey
{
OnBark, OnCry
}
public EventHandlerList EventList = new EventHandlerList();
public event ComplaintEventHandler OnBark
{
add
{
EventList.AddHandler(EventKey.OnBark, value);
}
remove
{
EventList.RemoveHandler(EventKey.OnBark, value);
}
}
var handler = EventList[eventKey] as ComplaintEventHandler;
>
handler = null
事实证明它不起作用。但是如果我使用声明为(as shown on)的键:
,它就可以工作static object EventKeyOnTap = new object();
在阅读了一些mscorlib的代码之后,我发现问题来自{/ 1}}
next.key == key
两个比较密钥都来自我的private EventHandlerList.ListEntry Find(object key)
{
EventHandlerList.ListEntry next = this.head;
while (next != null && next.key != key)
{
next = next.next;
}
return next;
}
,但它们不相等!
我想它来自于Enum
发生的一些隐式转换(列表中存储的密钥是object
类型)但是对于这种低级概念不够流畅。
我猜对了吗?
object
中使用Enum
作为关键字的最佳方法是什么? 现在,我将创建自己的 EventHandlerList
,其中EventHandlerList
为关键类型。
现在我创建了自己的Enum
,其构造函数采用了EventHandlerList
,然后我使用它来代替前面提到的相等比较。
答案 0 :(得分:3)
试试这段代码。你能解释输出吗?
var bark1 = (object)EventKey.OnBark;
var bark2 = (object)EventKey.OnBark;
Console.WriteLine(bark1 != bark2);
Console.WriteLine(bark1.Equals(bark2));
如果是,我不知道你为什么问这个问题。如果不是,您肯定应该了解值类型,引用类型和装箱。
简而言之,AddHandler
方法接受object
参数,因此当您致电时,您的密钥(值类型)会被加框:
EventList.AddHandler(EventKey.OnBark, value);
如果使用相同的枚举键调用此方法两次,则键将被装箱两次,并且实际上将创建堆中的两个不同对象。
这就是next.key != key
方法中的Find
检查失败的原因(它比较了堆中两个独立对象的地址)。
EventHandlerList是密封类,所以你不能影响它的内容,但是在你自己的代码中你可以通过更好的检查来处理这种情况:
next.key.Equals(key)