zoukankan      html  css  js  c++  java
  • C#基础加强篇----委托、Lamada表达式和事件(上)

    1.委托

          C#的委托相当于C/C++中的函数指针。函数指针用指针获取一个函数的入口地址,实现对函数的操作。

          委托与C/C++中的函数指针不同在于,委托是面向对象的,是引用类型,对委托的使用要先定义后实例化,最后才能调用。并且委托是类型安全的,它定义了返回类型和参数的类型,而在C/C++中,函数指针只是一个指向内存位置的指针,它不是类型安全的,我们无法判断这个指针实际指向什么,所以参数和返回类型等项就无法知道了。

       

          定义委托

             使用关键字delegate。语法类似于方法的定义,但没有方法体,定义的前面加上关键字delegate。

               例如:定义一个委托:delegate void IntMethod(int x);

                       在这个示例中,定义了一个委托IntMethod,并指定该委托的每个实例都可以包含一个方法的引用,该方法带有一个int参数,返回类型为void。

                       如果要定义一个委托TwoLongOp,该委托表示的方法有两个long类型的参数,返回类型为double,则可以这样定义:delegate double TwoLongOp(long first,long second);

                   delegate  string GetString();//该委托表示的方法没有参数,返回string类型。

         定义委托基本上是定义一个新类,可以在定义类的任何相同地方定义委托。也就是说可以在一个类的内部定义,也可以在外部定义,还可以在命名空间中把委托定义为顶层对象。

         可以在委托的定义上应用访问修饰符:public,protected,private等,用来限定委托的作用域。例如:public delegate void IntMethod(int x);

          

        实例化,调用 

     1   private  delegate string GetString(int x);//定义委托
     2         static void Main(string[] args)
     3         {
     4             GetString strMed = new GetString(StringMethod);//对委托进行实例化,并进行初始化
     5             Console.WriteLine(strMed(555));//调用委托
     6             Console.ReadKey();
     7         }
     8         private static string StringMethod(int x)
     9         {
    10             return x.ToString();
    11         } 

           注意,在C#中,委托总是接受一个参数的构造函数,这个参数就是委托引用的方法,这个方法必须匹配委托定义时的签名。本例中委托定义时,返回类型为string,参数类型为int,所以初始化变量strMed时的方法StringMethod也必须与之一致。

          类有两个不同的术语,“类”表示较广泛的定义,对象表示类的实例。但委托只有一个术语,在创建委托的实例时,所创建的委托实例仍称委托。

          还可以直接把委托所引用的方法直接赋值给委托类型的变量(委托推断),例:  GetString strMed =StringMethod;  

         

         Action<T>和Func<T>委托

         进一步简化了委托的定义,而不用显式声明自定义委托。

         泛型Action<T>委托表示引用一个void返回类型的方法,这个委托类存在不同的变体,最多可传递16种不同的参数类型。没有泛型参数的Action类调用没有参数的方法。

         public delegate void Action()      public delegate void Action<in T>(T obj)

         ......

        

     1    static void Main(string[] args)
     2         {
     3             Action<string> messageTarget;
     4             messageTarget = GetAStr;
     5             messageTarget("Action<T> Demo!");
     6             Console.ReadKey();
     7         }
     8         private static void GetAStr(string obj)
     9         {
    10             Console.WriteLine(obj);
    11         }

         Func<T>允许调用带返回类型的方法,与Action<T>类似,也定义了不同的变体,最多也可传递16种不同的参数类型和一个返回类型。

         public delegate TResult Func<out TResult>()

         public delegate TResult Func<in T, out TResult>(T arg)

         public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1,T2 arg2)      ......

     1  public static void Main()
     2     {
     3         Func<string, int, string[]> extractMethod = ExtractWords;//最后一个是返回值的类型,前面的都是参数的类型。
     4         string str = "helloawordaFunc";
     5         foreach (string word in extractMethod(str, 5))
     6             Console.WriteLine(word);
     7     }
     8     private static string[] ExtractWords(string phrase, int limit)
     9     {
    10         char[] delimiters = new char[] { 'a' };
    11         if (limit > 0)
    12             return phrase.Split(delimiters, limit);
    13         else
    14             return phrase.Split(delimiters);
    15     }

         多播委托

         一次委托调用多个方法,通过+和-运算符实现多播的增加或减少。多播委托包含已分配委托的列表。在调用多播委托时,它会按顺序调用列表中的委托。只能合并相同类型的委托。

      

     1     static void Main(string[] args)
     2         {
     3             Action del = D1;
     4             del += D2;
     5             del += D3;
     6             del();
     7             Console.WriteLine("------------------");
     8             del -= D2;
     9             del();
    10             Console.ReadKey();
    11         }
    12         private static void D1()
    13         {
    14             Console.WriteLine("I am D1");
    15         }
    16         private static void D2()
    17         {
    18             Console.WriteLine("I am D2");
    19         }
    20         private static void D3()
    21         {
    22             Console.WriteLine("I am D3");
    23         }

    msdn上的例子:

     1   static void Hello(string s)
     2     {
     3         System.Console.WriteLine("  Hello, {0}!", s);
     4     }
     5     static void Goodbye(string s)
     6     {
     7         System.Console.WriteLine("  Goodbye, {0}!", s);
     8     }
     9     static void Main()
    10     {
    11       
    12         CustomDel hiDel, byeDel, multiDel, multiMinusHiDel;
    13         hiDel = Hello;
    14 
    15         byeDel = Goodbye;
    16 
    17         multiDel = hiDel + byeDel;
    18 
    19         multiMinusHiDel = multiDel - hiDel;
    20 
    21         Console.WriteLine("Invoking delegate hiDel:");
    22         hiDel("A");
    23         Console.WriteLine("Invoking delegate byeDel:");
    24         byeDel("B");
    25         Console.WriteLine("Invoking delegate multiDel:");
    26         multiDel("C");
    27         Console.WriteLine("Invoking delegate multiMinusHiDel:");
    28         multiMinusHiDel("D");
    29     }

    Lamada表达式和事件将在下篇中介绍。。。。

  • 相关阅读:
    elementui问题汇总
    微信小程序实现微信授权登录
    微信小程序数据存储
    小程序使用第三方服务,需要中转到一个h5页面,返回到指定页面
    小程序开发,通过左上角返回到指定页面
    万恶之源-基本数据类型(list,tuple)
    基础中的基础
    mybatis_plus实现自动填充和逻辑删除
    本地端口占用解决方案
    maven定义版本以来报红解决方案
  • 原文地址:https://www.cnblogs.com/czhwust/p/4354478.html
Copyright © 2011-2022 走看看