分享
 
 
 

关于.NET的委托

王朝c#·作者佚名  2007-06-08
窄屏简体版  字體: |||超大  

.NET学习中,你碰到过委托吗?我接触.NET几个月以来,关于委托的确花了我好长时间才弄明白,这里我就C#中的委托给大家介绍一下。(先说定义和特征,然后用例子说明)

委托是回调函数的类型安全包装。C++编写的非托管程序进行回调时很容易出错。由于委托的存在,托管应用程序不会出现这样的情况。委托通常用来定义响应事件的回调方法的签名。

C#中的委托类似于C或C++中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内( 所以这里的“引用”不是原始内存地址,而是包装了方法的内存地址的委托实例 )。然后可以将给委托对象传递可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象、类型安全的,并且是安全的。

委托声明定义一种类型,它用一组特定的参数以及返回类型封装方法。

对于静态方法,委托对象封装要调用的方法。

对于实例方法,委托对象同时封装一个实例和该实例上的一个方法。

如果你有一个委托对象和一组适当的参数,则可以用这些参数调用该委托。

委托的一个有趣且有用的属性是: 它不知道或不关心自己引用的对象的类。任何对象都可以,知识方法的参数类型必须与委托的参数类型和返回类型相匹配。这是的委托完全适合“匿名”调用。

到现在已经说得不少了,现在开始用例子说明如何声明、实例化和调用委托:

下面的示例中,BookDB 类封装一个书店数据库,它维护一个书籍数据库。它公开 ProcessPaperbackBooks 方法,该方法在数据库中查找所有平装书,并为每本书调用一个委托。所使用的 delegate 类型称为 ProcessBookDelegate。Test 类使用该类输出平装书的书名和平均价格。委托的使用促进了书店数据库和客户代码之间功能的良好分隔。客户代码不知道书籍的存储方式和书店代码查找平装书的方式。书店代码也不知道找到平装书后将对平装书进行什么处理。

// bookstore.cs

using System;

//此命名空间中的几个类用以维护书籍数据库:

namespace Bookstore

...{

using System.Collections;

// 描述数据库中每一本书具有的属性:

public struct Book

...{

public string Title; // 书的题目.

public string Author; // 书的作者.

public decimal Price; // 书的价格.

public bool Paperback; // 是不是平装书?

public Book(string title, string author, decimal price, bool paperBack)

...{

Title = title;

Author = author;

Price = price;

Paperback = paperBack;

}

}

// 为处理平装书的类声明一个委托类型(delegate类型):

public delegate void ProcessBookDelegate(Book book);

// 维护书籍的数据库.

public class BookDB

...{

// 数据库中所有书籍的清单:

ArrayList list = new ArrayList();

// 向数据库中添加一本书:

public void AddBook(string title, string author, decimal price, bool paperBack)

...{

list.Add(new Book(title, author, price, paperBack));

}

// 对于每一本平装书调用ProcessBookDelegate这个委托,以对平装书进行处理:

public void ProcessPaperbackBooks(ProcessBookDelegate processBook)

...{

foreach (Book b in list)

...{

if (b.Paperback)

// Calling the delegate:

processBook(b);

}

}

}

}

// 使用Bookstore命名空间里的类:

namespace BookTestClient

...{

using Bookstore;

// 具有统计平装书并求出平装书的平均价格功能的类:

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 Test

...{

// 打印书籍题目的静态方法.

static void PrintTitle(Book b)

...{

Console.WriteLine(" {0}", b.Title);

}

// 程序执行的入口:

static void Main()

...{

BookDB bookDB = new BookDB();

// 用几本书来输初始化书籍数据库:

AddBooks(bookDB);

// 打印平装书的题目:

Console.WriteLine("Paperback Book Titles:");

// 创建与静态方法 Test.PrintTitle 关联的新的委托对象:

bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));

// 通过PriceTotaller的实例获取平装书的平均价格:

PriceTotaller totaller = new PriceTotaller();

// 创建与对象 totaller 上的非静态方法 AddBookToTotal 关联的新的委托对象:

bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));

Console.WriteLine("平装书的平均价格: ${0:#.##}",

totaller.AveragePrice());

}

// 向数据库添加书以初始化书籍数据库:

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);

}

}

}

输出:

Paperback Book Titles:

The C Programming Language

The Unicode Standard 2.0

Dogbert's Clues for the Clueless

平装书的平均价格: $23.97

声明委托 以下语句:

public delegate void ProcessBookDelegate(Book book);

声明一个新的委托类型。每个委托类型都描述参数的数目和类型,以及它可以封装的方法的返回值类型。每当需要一组新的参数类型或新的

返回值类型时,都必须声明一个新的委托类型。

实例化委托

声明了委托类型后,必须创建委托对象并使之与特定方法关联。与所有其他对象类似,新的委托对象用 new 表达式创建。

但是当创建委托时,传递给 new 表达式的参数很特殊:它的编写类似于方法调用,但没有方法的参数。

下列语句:

bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));

创建与静态方法 Test.PrintTitle 关联的新的委托对象。

下列语句:

bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));

创建与对象 totaller 上的非静态方法 AddBookToTotal 关联的新的委托对象。在例子中,新的委托对象都立即传递给 ProcessPaperbackBooks 方法。

请注意一旦创建了委托,它所关联到的方法便永不改变:委托对象不可改变。

调用委托

创建委托对象后,通常将委托对象传递给将调用该委托的其他代码。通过委托对象的名称(后面跟着要传递给委托的参数,括在括号内)

调用委托对象。下面是委托调用的示例:

processBook(b);

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有