C#在处理事件时需要显式委托声明

时间:2016-11-05 20:18:42

标签: c# delegates

我们都知道委托是函数指针。所以当我们使用事件然后我们声明委托但我想知道在处理像public delegate void OnButtonClickDelegate();

这样的事件时我们必须声明委托的情况

这里我引用的是一个代码示例,它显示我们可以在构建的委托EventHandler中使用,而不是显式声明委托。

public class ArgsSpecial : EventArgs
{
    public ArgsSpecial (string val)
    {
        Operation=val;
    }

    public string Operation {get; set;}
} 

public class Animal
{
    // Empty delegate. In this way you are sure that value is always != null 
    // because no one outside of the class can change it.
    public event EventHandler<ArgsSpecial> Run = delegate{} 

    public void RaiseEvent()
    {  
         Run(this, new ArgsSpecial("Run faster"));
    }
}

Animale animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();

所以当构建的委托中的EventHandler解决了我的目的时,我们不需要在处理事件时明确声明委托。所以告诉我我们必须明确声明委托,EventHandler可能无法解决我们的目的。感谢

2 个答案:

答案 0 :(得分:1)

EventHandler实际上有一个非常有限的签名,两个参数,其中第一个始终是object类型,第二个必须是继承System.EventArgs的类类型。但考虑到System.Action<T, ...>System.Func<T, ..., TReturn>,您很少需要声明另一个。事实上,如果Action和Func系列已经存在,那么大多数原始BCL委托类型MethodInvokerConverter<T, U>Predicate<T>甚至EventHandler<T>可能都不会被定义那个时候。

当你需要by-reference参数时,仍然需要声明你自己的委托。 refout关键字无法通过通用类型参数传递,因此如果您希望代理与TryParse系列匹配,则无法说Func<string, out T, bool>和需要一个自定义声明

/* return true if parsing successful */
delegate bool TryParser<T>(string from, out T into);

将by-reference参数与事件一起使用是非常罕见的,因此您可能永远不必声明委托用作事件类型。

答案 1 :(得分:0)

如果您希望接收的参数不是EventHandler

指定的参数,则需要自定义委托

例如,假设您的Animal课程在每次Animal试图吃掉它时都想要举起一个事件,这个事件可能需要发送捕食者和被攻击的动物。使用EventHandler,您需要创建一个新类作为两个动物的包装器并将其实例作为事件参数发送,它与委托更简单:

 public delegate void AttackedDelegate(Animal predator, Animal victim);
//...
public event AttackedDelegate OnAttacked;

虽然引入了Action<>代表,但我认为除了可读性之外,您需要声明自己的代理并不常见。所以上面的例子可以表示为

public event Action<Animal, Animal> OnAttacked;