对于初学C#的人来说,基础语法和C语言等编程语言大同小异,遇到的第一个新内容就是“委托”(delegate)以及委托衍生的“事件”。其实对于初学者,可以把委托对象理解为是一个“函数类型”的变量。
class A
{
//定义了一个“函数类型”,SomeDelegate类型的委托变量可接受无参数、无返回值的函数
//可以定义在类外或类中,但不能定义在方法内
public delegate void SomeDelegate();
}
internal class Program
{
static void SomeFunc()
{
Console.WriteLine("第一个方法!");
}
static void Main(string[] args)
{
//函数SomeFunc被赋值给了“函数类型”的变量somedelegate
A.SomeDelegate somedelegate = new A.SomeDelegate(SomeFunc);
//一个“函数常量”又被赋值给了somedelegation
somedelegate += () => Console.WriteLine("第二个方法!");
//执行这个“函数变量”
somedelegate();
}
}
而匿名函数就相当于是一个“函数常量”,就像普通常量不需要一个变量名一样。这里唯一的区别是,普通的赋值是后值覆盖前值,但委托变量赋值是叠加和减少。
事件是一种特殊的委托变量,它是类私有的。
class A
{
public delegate void SomeDelegate();
//事件是一种特殊的委托变量,只能定义在类中
//必须是public才能在其它地方定义事件的成员
public event SomeDelegate someEvent;
//事件的执行必须在定义它的类的方法中
public void DoEvent()
{
someEvent();
}
}
internal class Program
{
static void SomeFunc()
{
Console.WriteLine("第一个方法!");
}
static void Main(string[] args)
{
//使用事件必须创建类的实例
A a= new A();
a.someEvent += SomeFunc;
a.someEvent += () => Console.WriteLine("第二个方法!");
//和委托不一样,事件是私有的委托变量,不能直接执行事件,必须通过类实例的方法来触发
a.DoEvent();
}
}
按照.NET推荐的标准事件,对委托定义作修改,增加两个标准参数:
class A
{
public delegate void SomeDelegate(object o,EventArgs e);
public event SomeDelegate someEvent;
EventArgs ee;
public void DoEvent()
{
someEvent(this,ee);
}
}
internal class Program
{
static void SomeFunc(object o, EventArgs e)
{
Console.WriteLine("第一个方法!");
}
static void Main(string[] args)
{
A a = new A();
a.someEvent += SomeFunc;
a.someEvent += (object o, EventArgs e) => Console.WriteLine("第二个方法!");
a.DoEvent();
}
}
由于是标准定义,所以class A定义的前两行可以简写:
class A
{
public EventHandler someEvent;
EventArgs ee;
public void DoEvent()
{
someEvent(this, ee);
}
}
internal class Program
{
static void SomeFunc(object o, EventArgs e)
{
Console.WriteLine("第一个方法!");
}
static void Main(string[] args)
{
A a = new A();
a.someEvent += SomeFunc;
a.someEvent += (object o, EventArgs e) => Console.WriteLine("第二个方法!");
a.DoEvent();
}
}
大多数情况下标准事件不需要传递参数,EventArgs类的对象不能传递参数,如果要传递参数,必须创造一个EventArg类的派生类并增添字段,泛型EventHandler的作用就是改写最初的委托定义:
public delegate void SomeDelegate(object o,AEventArgs e);
这样,我们就可以在触发事件的时候传递参数:
public class AEventArgs:EventArgs
{
public string msg;
}
class A
{
public EventHandler<AEventArgs> someEvent;
AEventArgs ee=new AEventArgs();
public void DoEvent(string x)
{
ee.msg=x;
someEvent(this, ee);
}
}
internal class Program
{
static void SomeFunc(object o, EventArgs e)
{
Console.WriteLine((e as AEventArgs).msg);
}
static void Main(string[] args)
{
A a = new A();
a.someEvent += SomeFunc;
a.DoEvent("新的方法!");
}
}