委托、泛型与事件
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
publicstaticvoid invokeDelegate(AddDelegate del,int i,int j) { Console.WriteLine(del(i,j)); }
匿名方法作为函数参数
invokeDelegate( delegate(int i int j) i,int { returni +j; return i + j; },100,200);
Func<>范型委托所能接收的函数都有返回值, Func<>范型委托所能接收的函数都有返回值 那么,有没有接收返回void的函数的系统托
publicdelegatevoidAction(); bli d l t id A ti () publicdelegatevoidAction<T>(Tobj); publicdelegatevoidAction<T1,T2>(T1arg1,T2arg2) publicdelegatevoidAction<T1,T2,T3>(T1arg1,T2arg2,T3arg3) publicdelegatevoidAction<T1,T2,T3,T4>(T1arg1,T2arg2,T3arg3,T4arg4)
所有这些看上去复杂的声明,其实是很简单的: 所有 看 去复杂的声明 其实是很简单的 最后一个参数是委托所接收函数的返回值,前 面的参数(如果有的话)就是委托所接收函数 数 委 接收 数 的形参。
Func<>应用实例
Func<int,int,long>add=delegate(int a,int b) { returna*b; }; Console.WriteLine(add(5,10));
C#编译器对委托的处理方法
publicdelegateint MathOptDelegate(int value1,int value2);
上述委托将被编译器转换为:
publicclassMathOptDelegate :System.MulticastDelegate { publicMathOptDelegate(Objecttarget,Int32methodPtr); p publicvoidvirtualInvoke(Int32value1,Int32value2); ( , ); publicvirtualIAsyncResult BeginInvoke( , , y , j j ); Int32value1,Int32value2,AsyncCallbackcallback,Objectobject); publicvirtualvoidEndInvoke(IAsyncResult result); }
上述定义的委托,接收拥有一个到四个参 数,返回值类型为 数,返回值类型为void的函数。 的函数
Action<>实例
privatestaticvoidShowMessage(stringinfo) i t t ti id Sh M (ti i f ) { Console.WriteLine(info); ( ) } staticvoidMain(string[]args) { Action<string>act=ShowMessage; act("Hello"); ( ); }
委托的组合与分解
事实上,一个委托变量可以“引用”多个 函数,请看Demo( UseDelegate)。 g 引用多个函数的委托变量称为“多路委 托 托”。
多路委托变量 函数 函数 函数
委托调用链
7
从前面介绍的例子来看,使用委托 有以下几个步骤:
定义委托类型 定义 个或多个符合委托类型的函数 定义一个或多个符合委托类型的函数 定义委托类型的变量 将第2步定义的函数引用“挂接”到第3步 定义的变量,以形成 个 函数调用链 定义的变量,以形成一个“函数调用链”。 5. 通过委托变量“间接”调用函数调用链 1. 2. 2 3. 4.
匿名方法小结
在 在.NET2.0时代,匿名方法主要是作为简化 时代 匿名方法主要是作为简化 代码的手段而引入到C#2.0语法特性中的。 然而,也许设计者事先也并没有预想到, 这一原先仅出现在特定编程语言中的特性, 这 原先仅出现在特定编程语言中的特性 却成为了.NET3.5中的重要技术——LINQ的 基础之一。 基础之
2.3.2用于对象操作的委托
对象比较
publicdelegateintComparison<T>(Tx,Ty) 返回值 小于 0 0 大于0 说明 x<y y x=y x>y
使用Comparison<T>委托
Comparison<T>委托引用的函数可用于比较 委托引用的 数 用 比较 两个对象的大小。 示例:UseComparisonDelegate 使用一个对象比较器来确定两个对象“谁 使用 个对象比较器来确定两个对象“谁 大谁小”。List<T>对象使用此对象比较器进 行排序。
自定义事件的步骤(2)
定义 个事件委托 定义一个事件委托
publicdelegatevoidMyClickEventDelegate( Objectsender, MyClickEventArgs e );
2.2泛型委托
技术背景
泛型技术在 泛型技术在.NET2.0时代被加入到C#语言特 时代被加 到 言特 性中,因此,从.NET2.0开始,委托也开始 支持泛型,这就是“泛型委托”。
泛型委托示例
Demo:UseGenericDelegate 示例分析: 泛型委托的使用与普通委托类似,不同之 处在于使用泛型委托时需要指定类型参数。 处在于使用泛型委托时需要指定类型参数
系统预定义委托
.NET基类库中的预定义委托 NET基类库中的预定义委托
为了方便软件 程师 为了方便软件工程师,.NET基类库中针对在 基类库中针对在 实际开发中最常用的情形提供了几个预定 义好的委托,这些委托可以直接使用,无 需从头定义自己的委托类型。 预定义委托在.NET基类库中用得很广,需要 予以关注。 予以关注
Predicate<T>委托示例
Demo:UsePredicateDelegate 特点: 判断条件一般是“外在的”,而非由数据 自身指定的(比如要查找数组中最大的记 录)就不适合采用此委托
4使用委托定义事件
EventHandler委托
许多事件(比如事件的Click)的响应函数都拥有一 许多事件(比如事件的Click)的响应函数都拥有 致的格式,.NET提供了一个EventHandler委托用于 引用事件响应函数。
匿名方法其实是将方法定义与委托变量赋值两个步骤合在 一起。 起
探索匿名方法
使用 使用Reflectoor或者ilDasm查看C#编译器处 或者 查看 编译 处 理UseAnonymousMethod示例程序: y
委托类型可作为函数形参
一个接收委托类型变量作为参数的函数: 个接收委托类型变量作为参数的 数
委托 委托(Delegate):是.NETFramework对C# 是 对 和等编程语言特性的一个重要扩充。 委托是.NET中的一些重要技术,比如事件、 异步调用和多线程开发的技术基础。 异步调用和多线程开发的技术基础 委托在.NET开发中应用极广,每一名.NET软 件工程师都必须了解委托。
深入了解事件的技术内容
在 S 中可以查到 C 在MSDN中可以查到,Control.Click事件的定义如下: l Cli k事件的定义如下
p publiceventEventHandler Click; ; 由此可知,Click事件实际上就是一个EventHandler委托 类型的一个变量罢了! 类型的 个变量罢了! 还记得委托变量可以引用一个由多个函数首尾相接而成的 “函数调用链”吗? 利用这个特点,我们可以让Click事件发生时,连续调用多 个事件响应函数。 个事件响应函数 Demo:UseEventHandler2
引例:FirstDelegateExample
引例分析 引例分析: 1. 委托可以看成是 个函数的 容器 ,将 1 委托可以看成是一个函数的“容器”,将 某一具体的函数“装入”后,就可以把它 当成函数一样使用。 当成函数一样使用 2. 一个委托类型的变量,可以引用任何一个 满足其要求的函数。 从这点意义上看,委 托类似于C语言中的 函数指针 。 托类似于C语言中的“函数指针”。
2.3.1通用委托
Func<>委托
pub c de ega e esu u c publicdelegateTResult Func<TResult>(); esu (); publicdelegateTResult Func<T,TResult>(Targ) publicdelegateTResult Func<T1,T2,TResult>(T1arg1,T2arg2) publicdelegateTResultFunc<T1,T2,T3,TResult>( public delegate TResult Func<T1 T2 T3 TResult>( T1arg1,T2arg2,T3arg3) publicdelegateTResultFunc<T1,T2,T3,T4,TResult>( T1arg1,T2arg2,T3arg3,T4arg4) T1 arg1 T2 arg2 T3 arg3 T4 arg4)
查找对象
publicdelegatebool P di t T (T bj) bli d l t b l Predicate<T>(Tobj);
Predicate<T>委托接收一个函数引用,在函 Predicate<T>委托接收 个函数引用,在函 数内部书写代码表明此对象应满足的条件, 满足返回true。
publicdelegatevoidEventHandler( Objectsender,EventArgs e ) )
EventHandler委托可用于动态设定事件响应函数。
Demo:UseEventHandler
?EventHandler委托与
Click事件有何关系? Cli k事件有何关系?
问题: 上述步骤比较烦琐,能否进行简化?
2C#2.0对委托的简化
2.1匿名方法
(AnonymousMethods) (Anonymous Methods)
技术的应用场景
为了简化委托编程,C#引入了 匿名方法这一特性。
匿名方法的示例 ( UseAnonymousMethod )
定义委托 publicdelegateint AddDelegate(int i,int j); 使用匿名方法定义委托变量 AddDelegate del=delegate(int i,int j) { returni +j; }; Console.WriteLine(del(100,200)); ( ( , ));
如何自定义事件?
Demo:UseCustomEvent 设计一个可统计单击次数的按钮,它 提供一个自定义的MyClick事件 提供 个自定义的M Cli k事件
自定义事件的步骤(1)
定义 个事件参数 从E tA 类派生 定义一个事件参数,从EventArgs类派生
publicclassMyClickEventArgs :EventArgs bli l M Cli kE A E A { publicint public int ClickCount = 0; //单击次数 =0;//单击次数 publicMyClickEventArgs(int ClickCountValue):base() { ClickCount =ClickCountValue; } }
委托、泛型与事件 委托 泛型与事件
北京理 大学计算机学院 北京理工大学计算机学院 金旭亮
主要内容
1. 2. 2 3. 4. “委托”使用基础 委托 使用基础 C#2.0对委托的简化 C#2 0对委托的简化 .NET系统预定义委托 使用委托定义事件
1“委托”使用基础
什么是 委托 ? 什么是“委托”?
匿名方法作为函数参数
invokeDelegate( delegate(int i int j) i,int { returni +j; return i + j; },100,200);
Func<>范型委托所能接收的函数都有返回值, Func<>范型委托所能接收的函数都有返回值 那么,有没有接收返回void的函数的系统托
publicdelegatevoidAction(); bli d l t id A ti () publicdelegatevoidAction<T>(Tobj); publicdelegatevoidAction<T1,T2>(T1arg1,T2arg2) publicdelegatevoidAction<T1,T2,T3>(T1arg1,T2arg2,T3arg3) publicdelegatevoidAction<T1,T2,T3,T4>(T1arg1,T2arg2,T3arg3,T4arg4)
所有这些看上去复杂的声明,其实是很简单的: 所有 看 去复杂的声明 其实是很简单的 最后一个参数是委托所接收函数的返回值,前 面的参数(如果有的话)就是委托所接收函数 数 委 接收 数 的形参。
Func<>应用实例
Func<int,int,long>add=delegate(int a,int b) { returna*b; }; Console.WriteLine(add(5,10));
C#编译器对委托的处理方法
publicdelegateint MathOptDelegate(int value1,int value2);
上述委托将被编译器转换为:
publicclassMathOptDelegate :System.MulticastDelegate { publicMathOptDelegate(Objecttarget,Int32methodPtr); p publicvoidvirtualInvoke(Int32value1,Int32value2); ( , ); publicvirtualIAsyncResult BeginInvoke( , , y , j j ); Int32value1,Int32value2,AsyncCallbackcallback,Objectobject); publicvirtualvoidEndInvoke(IAsyncResult result); }
上述定义的委托,接收拥有一个到四个参 数,返回值类型为 数,返回值类型为void的函数。 的函数
Action<>实例
privatestaticvoidShowMessage(stringinfo) i t t ti id Sh M (ti i f ) { Console.WriteLine(info); ( ) } staticvoidMain(string[]args) { Action<string>act=ShowMessage; act("Hello"); ( ); }
委托的组合与分解
事实上,一个委托变量可以“引用”多个 函数,请看Demo( UseDelegate)。 g 引用多个函数的委托变量称为“多路委 托 托”。
多路委托变量 函数 函数 函数
委托调用链
7
从前面介绍的例子来看,使用委托 有以下几个步骤:
定义委托类型 定义 个或多个符合委托类型的函数 定义一个或多个符合委托类型的函数 定义委托类型的变量 将第2步定义的函数引用“挂接”到第3步 定义的变量,以形成 个 函数调用链 定义的变量,以形成一个“函数调用链”。 5. 通过委托变量“间接”调用函数调用链 1. 2. 2 3. 4.
匿名方法小结
在 在.NET2.0时代,匿名方法主要是作为简化 时代 匿名方法主要是作为简化 代码的手段而引入到C#2.0语法特性中的。 然而,也许设计者事先也并没有预想到, 这一原先仅出现在特定编程语言中的特性, 这 原先仅出现在特定编程语言中的特性 却成为了.NET3.5中的重要技术——LINQ的 基础之一。 基础之
2.3.2用于对象操作的委托
对象比较
publicdelegateintComparison<T>(Tx,Ty) 返回值 小于 0 0 大于0 说明 x<y y x=y x>y
使用Comparison<T>委托
Comparison<T>委托引用的函数可用于比较 委托引用的 数 用 比较 两个对象的大小。 示例:UseComparisonDelegate 使用一个对象比较器来确定两个对象“谁 使用 个对象比较器来确定两个对象“谁 大谁小”。List<T>对象使用此对象比较器进 行排序。
自定义事件的步骤(2)
定义 个事件委托 定义一个事件委托
publicdelegatevoidMyClickEventDelegate( Objectsender, MyClickEventArgs e );
2.2泛型委托
技术背景
泛型技术在 泛型技术在.NET2.0时代被加入到C#语言特 时代被加 到 言特 性中,因此,从.NET2.0开始,委托也开始 支持泛型,这就是“泛型委托”。
泛型委托示例
Demo:UseGenericDelegate 示例分析: 泛型委托的使用与普通委托类似,不同之 处在于使用泛型委托时需要指定类型参数。 处在于使用泛型委托时需要指定类型参数
系统预定义委托
.NET基类库中的预定义委托 NET基类库中的预定义委托
为了方便软件 程师 为了方便软件工程师,.NET基类库中针对在 基类库中针对在 实际开发中最常用的情形提供了几个预定 义好的委托,这些委托可以直接使用,无 需从头定义自己的委托类型。 预定义委托在.NET基类库中用得很广,需要 予以关注。 予以关注
Predicate<T>委托示例
Demo:UsePredicateDelegate 特点: 判断条件一般是“外在的”,而非由数据 自身指定的(比如要查找数组中最大的记 录)就不适合采用此委托
4使用委托定义事件
EventHandler委托
许多事件(比如事件的Click)的响应函数都拥有一 许多事件(比如事件的Click)的响应函数都拥有 致的格式,.NET提供了一个EventHandler委托用于 引用事件响应函数。
匿名方法其实是将方法定义与委托变量赋值两个步骤合在 一起。 起
探索匿名方法
使用 使用Reflectoor或者ilDasm查看C#编译器处 或者 查看 编译 处 理UseAnonymousMethod示例程序: y
委托类型可作为函数形参
一个接收委托类型变量作为参数的函数: 个接收委托类型变量作为参数的 数
委托 委托(Delegate):是.NETFramework对C# 是 对 和等编程语言特性的一个重要扩充。 委托是.NET中的一些重要技术,比如事件、 异步调用和多线程开发的技术基础。 异步调用和多线程开发的技术基础 委托在.NET开发中应用极广,每一名.NET软 件工程师都必须了解委托。
深入了解事件的技术内容
在 S 中可以查到 C 在MSDN中可以查到,Control.Click事件的定义如下: l Cli k事件的定义如下
p publiceventEventHandler Click; ; 由此可知,Click事件实际上就是一个EventHandler委托 类型的一个变量罢了! 类型的 个变量罢了! 还记得委托变量可以引用一个由多个函数首尾相接而成的 “函数调用链”吗? 利用这个特点,我们可以让Click事件发生时,连续调用多 个事件响应函数。 个事件响应函数 Demo:UseEventHandler2
引例:FirstDelegateExample
引例分析 引例分析: 1. 委托可以看成是 个函数的 容器 ,将 1 委托可以看成是一个函数的“容器”,将 某一具体的函数“装入”后,就可以把它 当成函数一样使用。 当成函数一样使用 2. 一个委托类型的变量,可以引用任何一个 满足其要求的函数。 从这点意义上看,委 托类似于C语言中的 函数指针 。 托类似于C语言中的“函数指针”。
2.3.1通用委托
Func<>委托
pub c de ega e esu u c publicdelegateTResult Func<TResult>(); esu (); publicdelegateTResult Func<T,TResult>(Targ) publicdelegateTResult Func<T1,T2,TResult>(T1arg1,T2arg2) publicdelegateTResultFunc<T1,T2,T3,TResult>( public delegate TResult Func<T1 T2 T3 TResult>( T1arg1,T2arg2,T3arg3) publicdelegateTResultFunc<T1,T2,T3,T4,TResult>( T1arg1,T2arg2,T3arg3,T4arg4) T1 arg1 T2 arg2 T3 arg3 T4 arg4)
查找对象
publicdelegatebool P di t T (T bj) bli d l t b l Predicate<T>(Tobj);
Predicate<T>委托接收一个函数引用,在函 Predicate<T>委托接收 个函数引用,在函 数内部书写代码表明此对象应满足的条件, 满足返回true。
publicdelegatevoidEventHandler( Objectsender,EventArgs e ) )
EventHandler委托可用于动态设定事件响应函数。
Demo:UseEventHandler
?EventHandler委托与
Click事件有何关系? Cli k事件有何关系?
问题: 上述步骤比较烦琐,能否进行简化?
2C#2.0对委托的简化
2.1匿名方法
(AnonymousMethods) (Anonymous Methods)
技术的应用场景
为了简化委托编程,C#引入了 匿名方法这一特性。
匿名方法的示例 ( UseAnonymousMethod )
定义委托 publicdelegateint AddDelegate(int i,int j); 使用匿名方法定义委托变量 AddDelegate del=delegate(int i,int j) { returni +j; }; Console.WriteLine(del(100,200)); ( ( , ));
如何自定义事件?
Demo:UseCustomEvent 设计一个可统计单击次数的按钮,它 提供一个自定义的MyClick事件 提供 个自定义的M Cli k事件
自定义事件的步骤(1)
定义 个事件参数 从E tA 类派生 定义一个事件参数,从EventArgs类派生
publicclassMyClickEventArgs :EventArgs bli l M Cli kE A E A { publicint public int ClickCount = 0; //单击次数 =0;//单击次数 publicMyClickEventArgs(int ClickCountValue):base() { ClickCount =ClickCountValue; } }
委托、泛型与事件 委托 泛型与事件
北京理 大学计算机学院 北京理工大学计算机学院 金旭亮
主要内容
1. 2. 2 3. 4. “委托”使用基础 委托 使用基础 C#2.0对委托的简化 C#2 0对委托的简化 .NET系统预定义委托 使用委托定义事件
1“委托”使用基础
什么是 委托 ? 什么是“委托”?