zoukankan      html  css  js  c++  java
  • 3 委托、匿名函数、lambda表达式

     

    在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法。C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方法,作为编写内联代码的首选方式

    复制代码
     // 声明一个委托
        delegate void Printer(string s);
        class TestClass
        {
            static void Main()
            {
                //lambda表达式
                Printer pp = x => { 
                    Console.WriteLine("print:" + x);
                };
    
                pp("sky");
    
    
    
                
    //匿名方法的语法:delegate(){//里边是代码块}
    // 摘要:
                //     Initializes a new instance of the System.Threading.Thread class.
                //
                // 参数:
                //   start:
                //     A System.Threading.ThreadStart delegate that represents the methods to be
                //     invoked when this thread begins executing.
                //
                // 异常:
                //   System.ArgumentNullException:
                //     The start parameter is null.
                System.Threading.Thread t1 = new System.Threading.Thread
                  (delegate()
                  {
                      System.Console.Write("Hello, ");
                      System.Console.WriteLine("World!");
                  });
                t1.Start();
    
    
                // 匿名函数
                Printer p = delegate(string j)
                {
                    System.Console.WriteLine(j);
                };
    
                // Results from the anonymous delegate call:
                p("The delegate using the anonymous method is called.");
    
    
    
                // 委托:将方法作为方法的参数
                //下边将方法绑定到委托
                //参考:张子阳的c#委托和事件http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html
                p = new Printer(TestClass.DoWork);
                p += TestClass.DoWork1;
                // p -= TestClass.DoWork;
                //p -= TestClass.DoWork1;
                // Results from the old style delegate call:
                p("The delegate using the named method is called.");
              
    
            }
    
            // The method associated with the named delegate:
            static void DoWork(string k)
            {
                System.Console.WriteLine(k);
            }
    
            static void DoWork1(string k)
            {
                System.Console.WriteLine(k);
            }
        }

    //无参数的委托
    复制代码
     // 声明一个委托
        delegate void del();
    
        class TestClass
        {
            static void Main()
            {
                del myDelegate1 = () =>
                {
                    Console.WriteLine("00xx");
                };
                myDelegate1();
    
    
                System.Threading.Thread t1 = new System.Threading.Thread
                 (()=>
                 {
                     System.Console.Write("Hello, ");
                     System.Console.WriteLine("World!");
                 });
                t1.Start();
    
    
                 t1 = new System.Threading.Thread
                 (delegate()
                 {
                     System.Console.Write("Hello, ");
                     System.Console.WriteLine("World!");
                 });
                t1.Start();
            }
        }
    复制代码
    
    
    
    
    
    复制代码

    MSDN上的委托例子:

    下面的示例阐释声明、实例化和使用委托。BookDB 类封装一个书店数据库,它维护一个书籍数据库。它公开 ProcessPaperbackBooks 方法,该方法在数据库中查找所有平装书,并对每本平装书调用一个委托。使用的 delegate 类型名为 ProcessBookDelegateTest 类使用该类打印平装书的书名和平均价格。

    委托的使用促进了书店数据库和客户代码之间功能的良好分隔。客户代码不知道书籍的存储方式和书店代码查找平装书的方式。书店代码也不知道找到平装书后将对平装书执行什么处理。

    复制代码
    // A set of classes for handling a bookstore:
    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:
        class TestBookDB
        {
            // Print the title of the book.
            static void PrintTitle(Book b)
            {
                System.Console.WriteLine("   {0}", b.Title);
            }
    
            // Execution starts here.
            static void Main()
            {
                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);
            }
        }
    }
    复制代码

    输出:

    Paperback Book Titles:
       The C Programming Language
       The Unicode Standard 2.0
       Dogbert's Clues for the Clueless
    Average Paperback Book Price: $23.97



    声明委托

    public delegate void ProcessBookDelegate(Book book);

    实例化委托。

    声明了委托类型后,必须创建委托对象并使之与特定方法关联。在上一个示例中,您通过按下面示例中的方式将 PrintTitle 方法传递到 ProcessPaperbackBooks方法来实现这一点:

    bookDB.ProcessPaperbackBooks(PrintTitle);

    这将创建与静态方法 Test.PrintTitle 关联的新委托对象。类似地,对象 totaller 的非静态方法 AddBookToTotal 是按下面示例中的方式传递的:

    bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);

    在两个示例中,都向 ProcessPaperbackBooks 方法传递了一个新的委托对象。

    委托创建后,它的关联方法就不能更改;委托对象是不可变的。

    调用委托。

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

    processBook(b);

    与本例一样,可以通过使用 BeginInvokeEndInvoke 方法同步或异步调用委托。 

    在C#中使用线程的方法很多,使用委托的BeginInvoke和EndInvoke方法就是其中之一。BeginInvoke方法可以使用线程异步地执行委托所指向的方法。然后通过EndInvoke方法获得方法的返回值(EndInvoke方法的返回值就是被调用方法的返回值),或是确定方法已经被成功调用。我们可以通过四种方法从EndInvoke方法来获得返回值。

    详情:这里

    分析:

    看起来 是不是很像接口啊 给后来着留一个委托 关注返回值和参数

    后来者实现委托 内部可以随便定义东东 但是 返回值和参数必须和委托的一样

    后来者想咋实现就咋实现

    何时使用委托何时使用接口呢 来自MSDN:

    复制代码
    委托和接口都允许类设计器分离类型声明和实现。任何类或结构都能继承和实现给定的接口。可以为任何类上的方法创建委托,前提是该方法符合委托的方法签名。接口引用或委托可由不了解实现该接口或委托方法的类的对象使用。既然存在这些相似性,那么类设计器何时应使用委托,何时又该使用接口呢?
    
    在以下情况下,请使用委托:
    
    当使用事件设计模式时。
    
    当封装静态方法可取时。
    
    当调用方不需要访问实现该方法的对象中的其他属性、方法或接口时。
    
    需要方便的组合。
    
    当类可能需要该方法的多个实现时。
    
    在以下情况下,请使用接口:
    
    当存在一组可能被调用的相关方法时。
    
    当类只需要方法的单个实现时。
    
    当使用接口的类想要将该接口强制转换为其他接口或类类型时。
    
    当正在实现的方法链接到类的类型或标识时:例如比较方法。
    
    使用单一方法接口而不使用委托的一个很好的示例是 IComparable 或泛型版本 IComparable<(Of <(T>)>)。IComparable 声明 CompareTo 方法,该方法返回一个整数,指定相同类型的两个对象之间的小于、等于或大于关系。IComparable 可用作排序算法的基础。虽然将委托比较方法用作排序算法的基础是有效的,但是并不理想。因为进行比较的能力属于类,而比较算法不会在运行时改变,所以单一方法接口是理想的





  • 相关阅读:
    简单明了的带你理解springboot原理和三大核心注解
    Spring Boot(一):入门篇
    【Mysql优化】聚簇索引与非聚簇索引概念
    Mysql索引原理与优化
    Mysql全文索引的使用
    索引的优缺点,如何创建索引
    184 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 04 例:字符串与byte(即:字节)数组间的相互转换
    183 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 03 String常用方法(下)
    182 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 02 String常用方法(上)
    181 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 01 String常用方法简介
  • 原文地址:https://www.cnblogs.com/hijushen/p/4242647.html
Copyright © 2011-2022 走看看