2

副标题:EventHandlerList 键的类型可以不是对象吗?

我想使用枚举存储我想在 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

事实证明它不起作用。但如果我使用声明为(如上所示)的键,它会起作用:

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;
}

两个比较的键都来自 my Enum,但它们不相等!我猜它来自一些隐式转换object(存储在列表中的键是 type object),但对这些低级概念不够流畅。

我的猜测对吗?

Enum在 an 中使用 an 作为键的最佳方法是EventHandlerList什么?

现在我将创建我自己EventHandlerListEnum作为键类型。

现在我EventHandlerList用一个构造函数创建了我自己的Func<object, object, bool>,然后我用它来代替前面提到的相等比较。

4

1 回答 1

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)
于 2012-09-06T14:24:48.123 回答