"创建并使用事件的步骤可以概括为事件建立代表,创建一个类来给事件处理程序传递参数,声明事件对应的代码,创建事件发生时执行的代码(处理程序)以及使事件发生"(最后一步可以理解为将事件处理程序和对象连接起来).
上面是书上讲的一段话,它说的倒轻松啊,我可理解了挺长时间的,这可以说是我学C#到现在学得最晕的一次.
首先说说代表,代表可以对应于C/C++当中的函数指针.看一个例子
namespace deleg1
{
public class SortClass
{
static public int val1;
static public int val2;
public delegate void Sort(ref int a,ref int b);//代表的声明,可以认为是一个类
public void DoSort(Sort ar)//创建一个函数,调用这个代表
{
ar(ref val1,ref val2);
}
}
/// <summary>
/// Class1 的摘要说明。
/// </summary>
class Class1
{
public static void Ascending(ref int first,ref int second)
{
if(first > second)
{
int tmp = first;
first = second;
second = tmp;
}
}
public static void Descending(ref int first,ref int second)
{
if(first < second)
{
int tmp = first;
first = second;
second = tmp;
}
}
public static void Add(ref int first,ref int second)
{
first += 1;
second += 1;
}
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
SortClass.Sort up = new SortClass.Sort(Ascending);//创建代表对象,将类给实例化了,可以认为是实例化了一个指针,得到方法的地址,以下两个相似.该方法的参数必须于Sort所声明的完全一致.
SortClass.Sort down = new SortClass.Sort(Descending);
SortClass.Sort add = new SortClass.Sort(Add);
SortClass doIT = new SortClass();//创建一个对象
SortClass.val1 = 310;
SortClass.val2 = 220;
Console.WriteLine("Before Sort: val1 = {0},val2 = {1}",
SortClass.val1,SortClass.val2);
doIT.DoSort(up);//这个对象就调用了这个代表,以下两个也一样.
Console.WriteLine("After Sort: val1 = {0},val2 = {1}",
SortClass.val1,SortClass.val2);
Console.WriteLine("Before Sort: val1 = {0},val2 = {1}",
SortClass.val1,SortClass.val2);
doIT.DoSort(down);
Console.WriteLine("After Sort: val1 = {0},val2 = {1}",
SortClass.val1,SortClass.val2);
doIT.DoSort(add);
Console.WriteLine("After Sort: val1 = {0},val2 = {1}",
SortClass.val1,SortClass.val2);
}
}
}
这是一个使用代表的简单例子.说白了,也就是像在C里面的设计一个函数,该函数的参数也是一个函数.但是整个过程还是有所不同的.C#是面向对象的.所有的东西都要用类的思想来看它.在则,代表跟接口有点相似,只不过它定义的是所要采取的方法和具体参数.但是接口没有.有一个共同点就是形式必须匹配,
using System;
namespace event1
{
delegate void CharEventHandler(object source,CharEventArgs e);//创建事件代表,第二个参数必须是EventArgs继承过来的.上面那个代表的参数是两个整数,而这里是两个用户自定义的对象.(为事件建立代表)
public class CharEventArgs : EventArgs//包含事件处理程序可以使用的数据
{ //EventArgs类用于将数据传给事件处理程序(创建一个类来给事件处理程序传递参数).
public char CurrChar;
public CharEventArgs(char CurrChar)//构造函数
{
this.CurrChar = CurrChar;
}
}
class CharChecker//创建一个引发事件的类,这个类包含在条件满足时引发事件的代码.(使事件发生)
{
char curr_char;
public event CharEventHandler TestChar;//事件的声明,TestChar用于给代表指定方法以及执行方法
public char Curr_Char
{
get { return curr_char;}
set
{
if(TestChar != null)//当没有对应的事件处理程序时这个值就为NULL,因为它是一个事件对象.
{
CharEventArgs args = new CharEventArgs(value);
TestChar(this,args);//调用代表
curr_char = args.CurrChar;
}
}
}
}
/// <summary>
/// Class1 的摘要说明。
/// </summary>
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
CharChecker tester = new CharChecker();
//将事件处理程序和该对象关联起来
tester.TestChar += new CharEventHandler(Drop_A);
tester.Curr_Char = 'B';//使事件发生
Console.WriteLine("{0}",tester.Curr_Char);
tester.Curr_Char = 'r';
Console.WriteLine("{0}",tester.Curr_Char);
tester.Curr_Char = 'a';
Console.WriteLine("{0}",tester.Curr_Char);
tester.Curr_Char = 'd';
Console.WriteLine("{0}",tester.Curr_Char);
}
static void Drop_A(object source,CharEventArgs e)//事件处理程序
{
if(e.CurrChar == 'a' || e.CurrChar == 'A')//声明事件对应的代码.
{
Console.WriteLine("Don't like 'a'!");
e.CurrChar = 'X';
}
}//该处理程序接受一个CharEventArgs参数.然后从该对象中取出CurrChar的值
} //并对其进行检查,作出相应处理
}
暂时就这么理解,还真有点搞不清楚.要理解事件,就要先理解代表的作用,这个是关键.