给代表属性的优雅方式

use*_*127 2 c# events delegates

假设我在课堂上有一些事件:

 class SomeClass{
     event ChangedEventHandler SomeDoubleChanged;
     double SomeDouble;
 }
Run Code Online (Sandbox Code Playgroud)

有:

 delegate void ChangedEventHandler(double d);
Run Code Online (Sandbox Code Playgroud)

现在假设我想在SomeDouble上侦听更改事件,但只想触发大于的更改delta.现在我可以做点什么

 SomeObject.SomeDoubleChanged += (d) => {if(abs(d-old_d) > delta){
                                  //do something     
                                 };
Run Code Online (Sandbox Code Playgroud)

但我希望我的活动能够解决这个问题,所以在最好的情况下我想做的事情如下:

 SomeObject.SomeDoubleChange += (delta, (d) => {});
Run Code Online (Sandbox Code Playgroud)

仍然允许:

 SomeObject.SomeDoubleChange += (d) => {};
Run Code Online (Sandbox Code Playgroud)

我只想实现它的唯一方法是删除整个事件关键字并使用+ =和 - =运算符实现一个容器,对指定的委托进行操作.但在我看来,这不是一个非常优雅的解决方案,因为它为SomeClass的用户提供了SomeDoubleChanged不是事件的想法.

这个问题最优雅的解决方案是什么?

Jon*_*eet 5

(我建议不要在这里使用术语"lambda",因为你也使用了lambda表达式.听起来你对变化感兴趣,即delta.)

您可以创建自己的静态方法来创建适当的委托:

public static ChangedEventHandler FilterByDelta(double delta,
                                                ChangedEventHandler handler)
{
    double previous = double.MinValue;
    return d =>
    {            
        if (d - previous > delta)
        {
            handler(d);
        }
        // Possibly put this in the "if" block? Depends on what you want.
        previous = d;
    };
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用:

SomeObject.SomeDoubleChange += Helper.FilterByDelta(5, d => ...);
Run Code Online (Sandbox Code Playgroud)

不幸的是,你不能在lambda表达式上使用扩展方法,这会使这更容易.