C#中事件的最佳实践

时间:2011-01-29 19:01:54

标签: c# events

在C#中,您可以在事件功能中使用返回值。但是,您只收到最后一个事件的返回值。此外,似乎没有办法获得上一个事件的返回值。

有哪些好的做法?我应该总是使用void吗?根据我有限的经验,如果我想要链值,我必须使用ref

我怎么写一个活动?我想使用Func< ref t,returnT>,但ref在那里是非法的,我想动作是一样的。 (我最终得到了以下内容)。有没有办法在使用ref

时使事件成为一行而不是两行
    delegate int FuncType(ref int a);
    static event FuncType evt;
    static void Main(string[] args)
    {
        evt += foo;
        var aa = 1;
        var a = evt(ref aa);
        evt += bar;
        var bb = 1;
        var b = evt(ref bb);
    }

    static int foo(ref int a)
    {
        a = a*3;
        return a;
    }

    static int bar(ref int a)
    {
        a=a +1;
        return a;
    }

5 个答案:

答案 0 :(得分:8)

如上所述,您可以使用GetInvocationList,这将允许您单独调用每个方法并处理返回的数据。

但在此之前,请考虑将EventHandler<T>EventArgs一起使用。

您可以在EventArgs中输入“所有”。 请查看以下示例代码:

public class BalanceChangedEventArgs : EventArgs
{
    public readonly double OldBalance;
    public readonly double NewBalance;

    public BalanceChangedEventArgs(double oldB, double newB)
    {
        OldBalance = oldB;
        NewBalance = newB;
    }
}

public class Account
{
    private double balance;

    public EventHandler<BalanceChangedEventArgs> balanceChanged;

    protected void OnBalanceChanged(BalanceChangedEventArgs eArgs)
    {
        if (balanceChanged != null)
            balanceChanged(this, eArgs);
    }

    public double Balance
    {
        get { return balance; }
        set
        {
            if (balance == value)
                return;

            OnBalanceChanged(new BalanceChangedEventArgs(balance, value));

            balance = value;
        }
    }
} 

答案 1 :(得分:7)

不要将“event”与“callback”混淆。如果您想为自定义提供“挂钩”,请考虑以下其中一项:

  • 带有虚拟挂钩方法的基类。
  • 传递给构造函数或通过属性访问的回调对象的接口。
  • 委托人传递给您的构造函数或通过属性访问。

如果您已考虑上述内容,但仍想使用某个事件,则可以将“结果”作为事件参数类型的一部分,例如e.Resulte.Handled。您仍然遇到多个事件处理程序可能会覆盖彼此的值的问题,因此您应该将该方法与其他答案所建议的迭代调用列表结合起来。要么整理所有结果,要么像e.Handled那样使用“提前退出”策略。

答案 2 :(得分:3)

您可能需要查看Microsoft的Event Design文档。

答案 3 :(得分:2)

如果您想在事件有多个订阅者时获取返回值,请使用Delegate.GetInvocationList。然后你可以说

foreach(FuncType d in evt.GetInvocationList()) {
    int value = d(parameter);
    // do something with value
}

但是,通常,最好避免在事件处理程序中返回值。

答案 4 :(得分:2)

“最佳做法”是仅使用void事件处理程序。正是因为最后一个价值问题。

如果需要组合结果,请定义具有适当属性的EventArgs后代。使用列表或总和值等。