将枚举元素作为事件参数传递给C#

时间:2016-09-13 19:46:35

标签: c# events enums delegates

是否可以将Enum元素作为事件参数传递?

让我说我有......

public class Letters
{
    public delegate void StateChangedEventHandler(object sender, EventArgs e);
    public event StateChangedEventHandler StateChanged;

    public AbcState state = AbcState.Aaa;     
    public AbcState State
    {
        get{return this.state;}
        set
        {
            this.state = value;
            this.OnStateChanged();
        }
    }

    public enum AbcState
    {
        Aaa,
        Bbb,
        Ccc
    }

    protected virtual void OnStateChanged()
    {
        StateChanged?.Invoke(this, State);
    }

看看我是如何尝试将枚举元素作为事件参数传递的? 现在,我通常会创建一个类并扩展EventArgs,然后我就能够传递类本身。 我知道我可以在这里做同样的事情,创建一个扩展EventArgs的不同类,然后在类中创建枚举,字段和属性。然后将后者的实例变成我的“Letters”类(在上面的代码中使用)。

但是,不是那么疯狂吗?一定有更好的方法。请告诉我有一种更简单的方法。

顺便说一句,我不知道上面的代码是否会编译,我只是直接在编辑器中编写它,因为我现在不在我的开发计算机上。

3 个答案:

答案 0 :(得分:2)

如果您希望事件的参数是枚举,那么请确定在声明事件时将其指定为签名:

public class Letters
{
    public event Action<AbcState> StateChanged;

    private AbcState state = AbcState.Aaa;     
    public AbcState State
    {
        get{return this.state;}
        set
        {
            this.state = value;
            this.OnStateChanged();
        }
    }

    public enum AbcState
    {
        Aaa,
        Bbb,
        Ccc
    }

    protected virtual void OnStateChanged()
    {
        StateChanged?.Invoke(State);
    }
}

答案 1 :(得分:2)

不,它并不那么疯狂。即使他们有时看起来有点笨拙也不是很疯狂,因为那些维护你的代码的人(包括你,在你忘记写这些东西之后)会发现尽可能少的惊喜。

但您可以选择使用EventHandler<T>

public event EventHandler<AbcState> StateChanged;

protected void OnStateChanged(AbcState state)
{
    StateChanged?.Invoke(this, state);
}

顺便说一下,您不必声明一个新的冗余委托类型来声明一个事件。这与您的原始声明相同:

public event EventHandler StateChanged;

最好的事情可能就是这样写:

public class ValueEventArgs<T> : EventArgs
{
    public ValueEventArgs(T value)
    {
        Value = value;
    }

    public T Value { get; protected set; }
}

并像这样使用它:

public event EventHandler<ValueEventArgs<AbcState>> StateChanged;

protected void OnStateChanged(AbcState state)
{
    StateChanged?.Invoke(this, new ValueEventArgs<AbcState>(state));
}

您还可以使用旧的和新的值属性等编写ValueChangedEventArgs<T>等。但是EventHandler<AbcState>是您最快速的类型安全方式来执行您想要的操作。

最后,您可以使用Action<T>作为event代表,但这不是一个好主意。人们看到Action<T>并且他们不希望它是event。当有人试图阅读你的代码时,你唯一要添加的就是混乱。除非有一些特定的,明确的优势(并且这里没有),否则不要编写代码,乍一看,这些代码看起来并不是什么。

答案 2 :(得分:2)

没有什么能阻止您不遵循事件处理程序约定:

public enum Test { X }

public class A
{
    public event Action<Test> StuffDone;    
}

你将能够做到这一点:

A a = new A();
a.StuffDone += test =>
{
    if(test == Test.X)
    {

    }
};

这只是一种惯例,而不是语言限制。