zoukankan      html  css  js  c++  java
  • 详细介绍有关于.NET的委托

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

  • 相关阅读:
    网页加速的14条优化法则 网站开发与优化
    .NET在后置代码中输入JS提示语句(背景不会变白)
    C语言变量声明内存分配
    SQL Server Hosting Toolkit
    An established connection was aborted by the software in your host machine
    C语言程序设计 2009春季考试时间和地点
    C语言程序设计 函数递归调用示例
    让.Net 程序脱离.net framework框架运行
    C语言程序设计 答疑安排(2009春季 110周) 有变动
    软件测试技术,软件项目管理 实验时间安排 2009春季
  • 原文地址:https://www.cnblogs.com/nianshi/p/797571.html
Copyright © 2011-2022 走看看