- 浏览: 256891 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (293)
- web (1)
- [随笔分类]项目管理 (30)
- [随笔分类]WCF (14)
- 未分类 (1)
- [随笔分类]Linq (4)
- [随笔分类]C#基础 (24)
- 项目 (1)
- [网站分类]3.非技术区(技术之外的文章,但不要涉及任何政治内容) (8)
- [网站分类]1.首页原创精华.NET区(包含架构设计、设计模式)(对首页文章的要求:原创、高质量、经过认真思考并精心写作) (9)
- [随笔分类]Ubuntu (4)
- ASP.Net (1)
- [网站分类]2..NET新手区(用于发表不合适发表在首页的.NET技术文章,包括小经验、小技巧) (30)
- [随笔分类]ASP.NET MVC (20)
- [随笔分类]ASP.NET (3)
- [随笔分类]程序员厨房 (4)
- [随笔分类]英语学习 (28)
- [网站分类]4.其他技术区 (1)
- [随笔分类]Silverlight (12)
- [随笔分类]CodeSmith (8)
- [随笔分类]其他 (4)
- [随笔分类]Ruby (4)
- [发布至博客园首页] (34)
- [网站分类]其他技术区 (3)
- [随笔分类]Ruby on Rails (2)
- [网站分类].NET新手区 (33)
- [随笔分类]TDD (1)
- [随笔分类]不谈技术 (2)
- [网站分类]非技术区 (7)
最新评论
-
yicone:
You make a mistake when paste t ...
WCF步步为营(一):简单示例 -
jinweijie:
你好,这个实现不错,但是在用了scriptmanager以后就 ...
在服务器端保存ViewState
一、委托概述
委托具有以下特点:
-
委托类似于 C++ 函数指针,但它们是类型安全的。
-
委托允许将方法作为参数进行传递。
-
委托可用于定义回调方法。
-
委托可以链接在一起;例如,可以对一个事件调用多个方法。
-
方法不必与委托签名完全匹配。(委托中的协变和逆变)
-
C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。这些功能统称为匿名函数
二、委托申明和使用示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//Description: 委托三种声明方式.net1.0到.net3.0
namespace NetTest
{
public class TestDelegateNet1To3
{
#region 不带返回值的委托
delegate void TestDelegate(string s);
public void TestAllDelegate()
{
//.net 1.0
TestDelegate en = new TestDelegate(M);
en("jack");
TestDelegate china = China;
china("wangdeshui");
//.net 2.0
TestDelegate delegateNet2 = delegate(string s) { Console.Out.WriteLine(s + ":这是一个2.0的方式"); };
delegateNet2("2.0 delegate declare");
//.net 3.0
TestDelegate delegateNet3 = (string s) => { Console.Out.WriteLine(s + ":这是3.0的方式"); };
delegateNet3("3.0 delegate declare");
TestReturn();
Func<int, bool> d = (n) => { return n > 10 ? true : false; };
Console.Out.WriteLine("func<int, bool>:" + d(20));
}
void M(string s)
{
Console.Out.WriteLine(s + ":Good Morning");
}
void China(string s)
{
Console.Out.WriteLine(s + ":早上好");
}
#endregion
#region 带返回值的委托测试
delegate bool TestDelegateReturn(int i);
void TestReturn()
{
TestDelegateReturn Net10 = new TestDelegateReturn(IsBig);
bool i = Net10(11);
Console.Out.WriteLine("Net10:" + i);
TestDelegateReturn Net20 = delegate(int j)
{
return (j > 10 ? true : false);
};
bool test20 = Net20(5);
Console.Out.WriteLine("Net20:" + test20);
TestDelegateReturn Net30 = (int k) => { return (k > 10 ? true : false); };
bool test30 = Net30(50);
Console.Out.WriteLine("Net30:" + test30);
}
bool IsBig(int i)
{
return i > 10 ? true : false;
}
#endregion
}
}
三、多播委托
调用委托时,它可以调用多个方法。这称为多路广播。若要向委托的方法列表(调用列表)中添加额外的方法,只需使用加法运算符或加法赋值运算符(“+”或“+=”)添加两个委托。
注意:
作为委托参数传递的方法必须与委托声明具有相同的签名。
委托实例可以封装静态或实例方法。
尽管委托可以使用 out 参数,但建议您不要将其用于多路广播事件委托,因为您无法知道哪个委托将被调用。多播委托传递值类型时,对参数的修改不会传到下一个
多播委托传递引用类型时,对引用参数的修改会传到下一个示例:
public class TestMultiCastDelegate
{
public delegate void Del(string message);
delegate void DelRef(Person p);
void MethodA(string s)
{
Console.Out.WriteLine("Method A:"+s);
}
void MethodB(string s)
{
s = "good";
Console.Out.WriteLine("Method B:" + s);
}
void MethodC(string s)
{
Console.Out.WriteLine("Method C:" + s);
}
/*
多播委托传递值类型时,对参数的修改不会传到下一个
多播委托传递引用类型时,对引用参数的修改会传到下一个
*
* */
public void Test()
{
//多播委托
Del d1 = MethodA;
Del d2 = MethodB;
Del d3=MethodC;
Del AllDelegateMethod = d1 + d2;
AllDelegateMethod += d3;
AllDelegateMethod("Jack");
/*
output:
ConsoleA: Jack
ConsoleB: Jack
ConsoleC:Jack
*/
Console.Out.WriteLine("---------------------");
AllDelegateMethod -= d3;
AllDelegateMethod("wangds");
//测试引用类型
DelRef dref1 = MethodRefA;
DelRef dref2 = MethodRefB;
DelRef Alldref = dref1 + dref2;
Person p = new Person { Address = "USA", Name = "America" };
Alldref(p);
}
//内嵌类
class Person
{
public string Name { get; set; }
public string Address { get; set; }
}
void MethodRefA(Person p)
{
Console.Out.WriteLine(p.Name + "," + p.Address);
Console.Out.WriteLine("----------MethodRefA---------");
p.Name = "Jack";
p.Address = "China";
Console.Out.WriteLine(p.Name + "," + p.Address);
Console.Out.WriteLine("----------MethodRefA---------");
}
void MethodRefB(Person p)
{
Console.Out.WriteLine("--------MethodRefB----------");
Console.Out.WriteLine(p.Name + "," + p.Address);
Console.Out.WriteLine("--------MethodRefB----------");
}
}
四、委托中的协变和逆变
委托中的协变: 就是允许方法的返回类型是委托的返回类型的子类
委托中的逆变,方法的参数是委托的参数的基类
示例:
#region 委托中的协变: 就是允许方法的返回类型是委托的返回类型的子类
class Mammals
{
}
class Dogs : Mammals
{
}
class XieBianDelegate
{
// Define the delegate.
public delegate Mammals HandlerMethod();
public Mammals FirstHandler()
{
return null;
}
public Dogs SecondHandler()
{
return null;
}
void Test()
{
HandlerMethod handler1 = FirstHandler;
// Covariance allows this delegate.
HandlerMethod handler2 = SecondHandler;
}
}
#endregion
#region 委托中的逆变,方法的参数是委托的参数的基类
class NiBianDelegate
{
public delegate Dogs HandlerNibianMethod(Dogs dogs);
public Dogs FirstHandlerNibian(Mammals mammals)
{
return null;
}
void Test()
{
Dogs dogs = new Dogs();
HandlerNibianMethod handNibian1 = FirstHandlerNibian;
}
}
#endregion
五、委托综合示例(来自MSDN)
下面的示例阐释声明、实例化和使用委托。BookDB 类封装一个书店数据库,它维护一个书籍数据库。它公开 ProcessPaperbackBooks 方法,该方法在数据库中查找所有平装书,并对每本平装书调用一个委托。使用的 delegate 类型名为 ProcessBookDelegate。Test 类使用该类打印平装书的书名和平均价格。
委托的使用促进了书店数据库和客户代码之间功能的良好分隔。客户代码不知道书籍的存储方式和书店代码查找平装书的方式。书店代码也不知道找到平装书后将对平装书执行什么处理。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Bookstore
{
using System.Collections;
// Describes a book in the book list:
public struct Book
{
public string Title; // Title of the book.
public string Author; // Author of the book.
public decimal Price; // Price of the book.
public bool Paperback; // Is it paperback?
public Book(string title, string author, decimal price, bool paperBack)
{
Title = title;
Author = author;
Price = price;
Paperback = paperBack;
}
}
// Declare a delegate type for processing a book:
public delegate void ProcessBookDelegate(Book book);
// Maintains a book database.
public class BookDB
{
// List of all books in the database:
ArrayList list = new ArrayList();
// Add a book to the database:
public void AddBook(string title, string author, decimal price, bool paperBack)
{
list.Add(new Book(title, author, price, paperBack));
}
// Call a passed-in delegate on each paperback book to process it:
public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
{
foreach (Book b in list)
{
if (b.Paperback)
// Calling the delegate:
processBook(b);
}
}
}
}
// Using the Bookstore classes:
namespace BookTestClient
{
using Bookstore;
// Class to total and average prices of books:
class PriceTotaller
{
int countBooks = 0;
decimal priceBooks = 0.0m;
internal void AddBookToTotal(Book book)
{
countBooks += 1;
priceBooks += book.Price;
}
internal decimal AveragePrice()
{
return priceBooks / countBooks;
}
}
// Class to test the book database:
public class TestBookDB
{
// Print the title of the book.
void PrintTitle(Book b)
{
System.Console.WriteLine(" {0}", b.Title);
}
// Execution starts here.
public void Test()
{
BookDB bookDB = new BookDB();
// Initialize the database with some books:
AddBooks(bookDB);
// Print all the titles of paperbacks:
System.Console.WriteLine("Paperback Book Titles:");
// Create a new delegate object associated with the static
// method Test.PrintTitle:
bookDB.ProcessPaperbackBooks(PrintTitle);
// Get the average price of a paperback by using
// a PriceTotaller object:
PriceTotaller totaller = new PriceTotaller();
// Create a new delegate object associated with the nonstatic
// method AddBookToTotal on the object totaller:
bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);
System.Console.WriteLine("Average Paperback Book Price: ${0:#.##}",
totaller.AveragePrice());
}
// Initialize the book database with some test books:
static void AddBooks(BookDB bookDB)
{
bookDB.AddBook("The C Programming Language", "Brian W. Kernighan and Dennis M. Ritchie", 19.95m, true);
bookDB.AddBook("The Unicode Standard 2.0", "The Unicode Consortium", 39.95m, true);
bookDB.AddBook("The MS-DOS Encyclopedia", "Ray Duncan", 129.95m, false);
bookDB.AddBook("Dogbert's Clues for the Clueless", "Scott Adams", 12.00m, true);
}
}
}
发表评论
-
C#拾遗系列(1):委托
2008-06-11 14:43 596一、委托概述 委托具有以下特点: 委托类似于 ... -
C#拾遗系列(2):属性
2008-06-11 14:54 7161. 这里主要演示属性的继承和覆盖 2. 把属性理解为方法 ... -
C#拾遗系列(3):构造函数
2008-06-11 15:19 6171. 主要演示构造函数的继承 声明空 ... -
C#拾遗系列(4):索引器
2008-06-11 15:30 7701. 概述 索引器允许类或结构的实例就像数组一样进行索引。索引 ... -
C#拾遗系列(5):泛型委托
2008-06-14 17:25 588using System; using System.Col ... -
C#拾遗系列(6):迭代器
2008-06-14 23:03 5221. 示例: using System; using Sys ... -
C#拾遗系列(7):自定义属性
2008-06-18 14:52 6451 .描述 属性提供功能强大的方法以将声明信息与 C# 代码( ... -
C#拾遗系列(8):异常
2008-06-19 11:02 597using System; using System.Col ... -
C#拾遗系列(9):继承、接口、扩展方法、分部类、类操作、Ref and Out、可空类型
2008-06-19 15:07 1150本文内容: 继承 Equal示例 结构和类 ... -
MSIL(0):简介
2009-03-04 23:06 860Microsoft Intermediate Language ... -
MSIL(1): Hello World
2009-03-09 22:14 7751. 用记事本编写如下代码 .assembly HelloWo ... -
代码段:ASCII to Unicode
2009-04-17 10:44 7891: private string Co ... -
Get countries from system
2009-05-08 16:02 8021: using System; 2: usi ... -
[Tips]:Read value from Resource file in C#
2009-05-18 16:18 10341: //Namespace refer ... -
[tips]: 多线程 ManualResetEvent
2009-05-21 14:23 1340WaitHandle用于实现对共享资源的独占访问,AutoRe ... -
C#拾遗系列(2):属性
2008-06-11 14:54 6011. 这里主要演示属性的继承和覆盖 2. 把属性理解为方法 ... -
C#拾遗系列(3):构造函数
2008-06-11 15:19 6321. 主要演示构造函数的继承 ... -
C#拾遗系列(4):索引器
2008-06-11 15:30 5921. 概述 索引器允许类或结构的实例就像数组一样进行索引。索引 ... -
C#拾遗系列(5):泛型委托
2008-06-14 17:25 682using System; using System.Col ... -
C#拾遗系列(6):迭代器
2008-06-14 23:03 7141. 示例: using System; using Sys ...
相关推荐
在C#编程语言中,委托扮演着至关重要的角色,它是一种类型安全的函数指针,允许我们传递方法作为参数或存储方法以供后续调用。本文将深入探讨C#中的委托,特别是匿名委托以及它们在实际应用中的用法,并提供相应的源...
在C#编程语言中,委托(Delegate)是一种强大的特性,它允许我们把方法作为参数传递,或者存储在变量中,从而实现回调函数和事件处理。本文将深入探讨C#委托的概念、用途、类型以及如何使用`DynamicInvoke`方法。 #...
Modern C#(11):深入“委托和事件” (Level 300) 讲 师:俞晖 MSDN 特邀讲师 课程简介:本次课程是系列课程《现代软件开发——使用.NET与C#》的第十一讲(即重开第一讲), 这次系列讲座的目的是为希望从...
[第25讲:委托与事件实例浅析(C#视频教程 + C#源代码).zip] 根据【田洪川 天轰穿 C#视频教程】的【第25讲:委托与事件实例浅析】实现,VS2010编译运行正常。 源代码与视频教程中略有不同! 本人不是天轰穿,在此对...
.NET/C#⾯试题汇总系列:集合、异常、泛型、LINQ、委托、EF! .NET/C#⾯试题汇总系列:多线程 .NET/C#⾯试题汇总系列:ASP.NET MVC .NET/C# ⾯试题汇总系列:ASP.NET Core .NET/C#⾯试题汇总系列:ADO.NET、XML、...
6. **事件处理**:委托在C#事件处理模型中扮演重要角色。事件是对象之间的通信机制,而事件处理程序通常通过委托实现。事件源对象发布事件,其他对象订阅事件并提供处理程序。 7. **委托的内存管理**:由于委托是...
开发语言:C# 参考网络上流传的《勇者斗恶龙》游戏源码制作的一个射击类游戏,借用了《勇者斗恶龙》的游戏界面及部分源码。 整个游戏框架已基本完成,源码中采用了一些设计模式,有精美的游戏画面和详尽的代码注释,...
1. **委托的定义**: 委托在C#中是一种类型,它类似于函数指针,但比函数指针更安全,因为它是类型安全的。声明委托时,我们需要使用`delegate`关键字,定义一个方法签名,表示该委托可以指向的方法应具有的参数...
5. **事件处理**:委托在事件驱动编程中的应用,如何声明、触发和订阅事件。 接下来,我们来看看四个实现委托的小程序可能涉及的主题: 1. **基本委托示例**:一个简单的程序,演示如何声明委托、实例化并调用委托...
编程学C#(1):VS2010 C# Access数据库管理程序,1. 基于VS2010 C# 的的Access数据库管理设计; 2. 数据集的创建; 3. .NET组件,dataGridview 控件的使用; 4. 数据库的插入、删除、查询操作设计。
C# 多线程利用委托更新控件内容 在 C# 编程中,多线程编程是常见的场景之一,特别是在需要实时更新控件内容的情况下。为了解决多线程之间的数据更新问题,本文将介绍如何使用委托(delegate)来更新控件的内容。 ...
在C#编程语言中,委托和事件是两个关键的概念,它们是实现面向对象设计模式,尤其是事件驱动编程的核心。下面将详细阐述这两个概念及其在实际编程中的应用。 **委托** 委托在C#中相当于一种类型,它封装了指向方法...
[第26讲:深入委托(C#视频教程 + C#源代码).zip] 根据【田洪川 天轰穿 C#视频教程】的【第26讲:深入委托】实现,VS2010编译运行正常。 源代码与视频教程中略有不同! 本人不是天轰穿,在此对田洪川老师表示感谢!
- **面向对象**:委托是面向对象的一部分,这意味着它们可以绑定到对象实例,并可以访问该对象的状态。 #### 如何声明和使用委托 ##### 1. 声明委托 使用`delegate`关键字声明一个新的委托类型。委托的声明通常...
金旭亮《C#面向对象程序设计》教案_6:委托与事件。此教案重点介绍.NET平台上的重要技术——委托,以及对建立于委托基础之上的.NET事件响应机制的深入剖析。包括两个29页的PDF文档及数个VS2010示例。前几讲的教案请...
1. **委托(Delegate)**: 委托在C#中是一种类型,它代表一个方法的引用。它可以像处理其他类型一样被传递给方法,也可以作为方法的返回值。在Winform中,委托经常用于事件处理,使代码能够异步执行。例如,当启动一...
1. **Direct Exchange**(直连交换机):最简单的交换机类型,按照路由键(Routing Key)将消息精确地投递给对应的队列。在C#项目中,可以创建一个DirectExchange类,设置路由键和队列绑定,实现一对一的消息传递。 ...
3. 事件和事件处理程序:委托在事件处理中也扮演重要角色,通过+=运算符订阅事件,使用-=取消订阅。 三、UI更新与委托 在多线程环境中,由于UI线程和后台线程之间的同步问题,直接在非UI线程上修改UI元素可能会导致...
在C#编程中,"跨窗体更新-委托实例"是一个关键的概念,它涉及到多窗口应用程序的通信和数据同步。本文将深入探讨这个主题,并通过一个具体的实例来讲解如何使用委托来实现窗体间的交互。 首先,理解"跨窗体更新...