副标题:EventHandlerList 键的类型可以是对象以外的类型吗?
我想使用枚举存储我想要在事件处理程序中拥有的键。
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 的代码后,我发现问题来自 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;
}
两个比较的 key 都来 self 的 Enum
,但它们并不相等!
我猜它来自对 object
的一些隐式转换正在发生(列表中存储的键的类型为 object
),但我对如此低级的概念不够流畅。
我的猜测对吗?
使用 Enum
的最佳方式是什么?作为 EventHandlerList
中的键?
现在我将创建自己的 EventHandlerList
与 Enum
作为键类型。
现在我创建了自己的 EventHandlerList
构造函数采用 Func<object, object, bool>
然后我用它来代替前面提到的相等比较。
最佳答案
试试这个代码。你能解释一下输出吗?
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);
如果使用相同的枚举键调用此方法两次,键将被装箱两次,并且实际上会在堆中创建两个不同的对象。
这就是 Find
方法中的检查 next.key != key
失败的原因(它比较堆中两个单独对象的地址)。
EventHandlerList 是密封类,因此您不能影响其内部,但在您自己的代码中,您可以通过更好的检查来处理这种情况:
next.key.Equals(key)
关于c# - 枚举相等(和 EventHandlerList 的键),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12301676/