我正在阅读关于genrics的msdn库主题。有一个用泛型委托声明事件的例子,但它是否正确?
// Code block 8. Generic event handling
public delegate void GenericEventHandler<S,A>(S sender,A args);
public class MyPublisher
{
public event GenericEventHandler<MyPublisher,EventArgs> MyEvent;
public void FireEvent()
{
MyEvent(this,EventArgs.Empty);
}
}
public class MySubscriber<A> //Optional: can be a specific type
{
public void SomeMethod(MyPublisher sender,A args)
{...}
}
MyPublisher publisher = new MyPublisher();
MySubscriber<EventArgs> subscriber = new MySubscriber<EventArgs>();
publisher.MyEvent += subscriber.SomeMethod; // is this line correct?
我们可以直接将方法应用于事件,而不首先将其与我们的代表包装在一起吗?
答案 0 :(得分:6)
是的,这是C#2.0中的新功能,它将为您创建代理。请注意,您仍在创建委托,但创建是不可见的。
答案 1 :(得分:1)
publisher.MyEvent += subscriber.SomeMethod;
在上面一行中,右侧表达式“subscriber.SomeMethod”的类型为GenericEventHandler(S sender,A args)。
正如对象是类类型的实例一样,方法也是委托类型的实例。 类指定对象的模板...委托指定方法的签名....即参数和返回类型。委托类型的变量只是对一个或多个方法的引用,这些方法的签名符合委托声明中指定的方法。
在旧版本的C#中,您必须编写如下内容:
publisher.MyEvent +=
new GenericEventHandler<MyPublisher,EventArgs>(subscriber.SomeMethod);
在较新版本的C#中,当您只提供subscriber.SomeMethod时,会自动推断出右侧那个长丑看的表达式的类型。它是由SomeMethod的签名以及MyEvent的类型推断出来的......它是指定签名的委托。
如果SomeMethod中的代码非常简单,并且您不会从程序中的任何其他位置调用它,则可以完全避免在命名方法(如SomeMethod)中编写它,而是使用匿名方法语法,如下所示并编写它然后:
publisher.MyEvent += delegate(MyPublisher s, EventArgs a)
{
/* the SomeMethod Code */
};
甚至更好,使用如下的Lambda表达式:
publisher.MyEvent += (s, a) => {/*the SomeMethod code*/};
在上面的lambda表达式中,参数's'和'a'的类型是从MyEvent的类型自动推断出来的。 ......当然是指定签名的代表。
现在只要MyEvent在匿名方法中触发代码,或者将执行lambda表达式。
答案 2 :(得分:0)
我认为它叫做委托推理。但无论它被称为完全合法使用。它在c#3.0中添加了语法糖
如果你需要了解通用代表和事件的工作
,也许你应该使用它using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Generic_Delegates_and_Events
{
public delegate void GenericEventHandler<S,A>(S sender,A args); //generic delegate
public class MyPublisher
{
public event GenericEventHandler<MyPublisher,EventArgs> MyEvent;
public void FireEvent()
{
MyEvent(this,EventArgs.Empty);
}
}
public class MySubscriber<A> //Optional: can be a specific type
{
public void SomeMethod(MyPublisher sender,A args)
{
Console.WriteLine("MySubscriber::SomeMethod()");
}
}
public class MySubscriber2<A> //Optional: can be a specific type
{
public void SomeMethod2(MyPublisher sender, A args)
{
Console.WriteLine("MySubscriber2::SomeMethod2()");
}
}
class Program
{
static void Main(string[] args)
{
MyPublisher publisher = new MyPublisher();
MySubscriber<EventArgs> subscriber = new MySubscriber<EventArgs>();
publisher.MyEvent += subscriber.SomeMethod;
MySubscriber2<EventArgs> subscriber2 = new MySubscriber2<EventArgs>();
publisher.MyEvent += subscriber2.SomeMethod2;
publisher.FireEvent();
}
}
}