• C#基础Func,Action


    Func,Action
    的介绍及其用法

    Func是一种委托,这是在3.5里面新增的,2.0里面我们使用委托是用Delegate,Func位于System.Core命名空间下,使用委托可以提升效率,例如在反射中使用就可以弥补反射所损失的性能。

    Action<T>和Func<T,TResult>的功能是一样的,只是Action<T>没有返类型,

    Func<T,T,Result>:有参数,有返回类型
    Action,则既没有返回也没有参数,


    Func<T,TResult>
    的表现形式分为以下几种:

    1。Func<T,TResult>
    2。Func<T,T1,TResult>
    3。Func<T,T1,T2,TResult>
    4。Func<T,T1,T2,T3,TResult>
    5。Func<T,T1,T2,T3,T4,TResult>

    分别说一下各个参数的意义,TResult表示
    委托所返回值 所代表的类型, T,T1,T2,T3,T4表示委托所调用的方法的参数类型,

    以下是使用示例:

    Func<int, bool> myFunc = null;//全部变量

    myFunc = x => CheckIsInt32(x);
    //给委托封装方法的地方 使用了Lambda表达式

    private bool CheckIsInt32(int pars)//被封装的方法
    {
      return pars == 5;
    }

      bool ok = myFunc(5);//调用委托

    MSDN:http://msdn.microsoft.com/zh-cn/library/bb534303(VS.95).aspx



    但是如果我们需要所封装的方法不返回值,增么办呢?就使用Action!

    可以使用
    Action<T1, T2, T3, T4>委托以参数形式传递方法,而不用显式声明自定义的委托。封装的方法必须与此委托定义的方法签名相对应。也就是说,封装的方法必须具有四个均通过值传递给它的参数,并且不能返回值。(在 C# 中,该方法必须返回 void。在 Visual Basic 中,必须通过 Sub…End Sub 结构来定义它。)通常,这种方法用于执行某个操作。

    使用方法和Func类似!

    MSDN:http://msdn.microsoft.com/zh-cn/library/bb548654(VS.95).aspx


    Action:既没有返回,也没有参数,使用方式如下:

    Action
    action = null;//定义action

    action =  CheckIsVoid;//封装方法,只需要方法的名字

    action();//调用



    总结:使用Func<T,TResult>和Action<T>,Action而不使用Delegate其实都是为了简化代码,使用更少的代码达到相同的效果,不需要我们显示的声明一个委托,Func<T,TResult>的最后一个参数始终是返回类型,而
    Action<T,TResult>是没有返回类型的,而Action是没有返回类型和参数输入的。






    Action<T>泛型委托


    描述:

        封装一个方法,该方法只采用一个参数并且不返回值.

    语法:

        public delegate void Action<T>(T arg);

    T:

        参数类型:此委托封装的方法的参数类型

    arg:

        参数:此委托封装的方法的参数

    备注:

        通过此委托,可以将方法当做参数进行传递.

    其他形式:

        public
    delegate void Action<T1, T2>(T1 arg1, T2 arg2);
        public delegate
    void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
        public delegate
    void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4
    arg4);

    例子:

        protected void Page_Load(object sender, EventArgs
    e)
        {
            List<int> list = new
    List<int>();
            list.AddRange(new int[] { 7, 6, 10, 1, 2, 3, 4, 5,
    8 });

            Action<int> action = new
    Action<int>(AddFive);
            list.ForEach(action);

            //效果同
            //      Action<int>
    action = new
    Action<int>(AddFive);
            //      list.ForEach(action);
            //list.ForEach(x
    => Response.Write((x + 5).ToString() +
    "<br/>"));

            //效果同
            //      Action<int>
    action = new
    Action<int>(AddFive);
            //      list.ForEach(action);
            //list.ForEach(delegate(int
    i)
            //{
            //    HttpContext.Current.Response.Write((i +
    5).ToString() + "<br/>");
            //});
        }

        public
    static void AddFive(int
    i)
        {
            HttpContext.Current.Response.Write((i + 5).ToString() +
    "<br/>");
        }

    结果:

        12
        11
        15
        6
        7
        8
        9
        10
        13




    Action<(Of
    <(T>)> 委托 讲解(MSDN)
    Posted on 2009-09-30 11:09 jowo 阅读(128) 评论(0) 编辑
    收藏

    说明:封装一个方法,该方法只采用一个参数并且不返回值。

    命名空间:  System
    程序集:  mscorlib(在
    mscorlib.dll 中)
      C#

    public delegate void Action<T>(
        T
    obj
    )

    类型参数

    T

        此委托封装的方法的参数类型。

    参数

    obj
        类型:T
        此委托封装的方法的参数。

    备注

    可以使用此委托以参数形式传递方法,而不用显式声明自定义的委托。该方法必须与此委托定义的方法签名相对应。也就是说,封装的方法必须具有一个通过值传递给它的参数,并且不能返回值。(在
    C# 中,该方法必须返回 void。在 Visual Basic 中,必须通过 Sub…End Sub 结构来定义它。)
    通常,这种方法用于执行某个操作。
    018hxwa8.alert_note(zh-cn,VS.90).gif说明:

    若要引用具有一个参数并返回值的方法,请改用泛型
    Func<(Of <(T, TResult>)>) 委托。

    在使用 Action<(Of
    <(T>)>) 委托时,不必显式定义一个封装只有一个参数的方法的委托。例如,以下代码显式声明了一个名为 DisplayMessage
    的委托,并将对 WriteLine 方法或 ShowWindowsMessage
    方法的引用分配给其委托实例。
    C#
    复制代码

    using System;
    using
    System.Windows.Forms;

    delegate void DisplayMessage(string
    message);

    public class TestCustomDelegate
    {
       public static void
    Main()
       {
          DisplayMessage messageTarget;

          if
    (Environment.GetCommandLineArgs().Length > 1)
             messageTarget =
    ShowWindowsMessage;
          else
             messageTarget =
    Console.WriteLine;

          messageTarget("Hello, World!");  
      
    }     

       private static void ShowWindowsMessage(string message)
      
    {
          MessageBox.Show(message);     
      
    }
    }

    以下示例简化了此代码,它所用的方法是实例化 Action<(Of <(T>)>)
    委托,而不是显式定义一个新委托并将命名方法分配给该委托。
    C#
    复制代码

    using System;
    using
    System.Windows.Forms;

    public class TestAction1
    {
       public static
    void Main()
       {
          Action<string> messageTarget;


          if (Environment.GetCommandLineArgs().Length > 1)
            
    messageTarget = ShowWindowsMessage;
          else
             messageTarget =
    Console.WriteLine;

          messageTarget("Hello, World!");  
      
    }     

       private static void ShowWindowsMessage(string message)
      
    {
          MessageBox.Show(message);     
       }
    }

    您也可以按照以下示例所演示的那样在
    C# 中将 Action<(Of <(T>)>) 委托与匿名方法一起使用。(有关匿名方法的简介,请参见匿名方法(C#
    编程指南)。)
    C#
    复制代码

    using System;
    using
    System.Windows.Forms;

    public class TestAnonMethod
    {
       public
    static void Main()
       {
          Action<string> messageTarget;


          if (Environment.GetCommandLineArgs().Length > 1)
            
    messageTarget = delegate(string s) { ShowWindowsMessage(s);
    };
          else
             messageTarget = delegate(string s) {
    Console.WriteLine(s); };

          messageTarget("Hello, World!");
      
    }

       private static void ShowWindowsMessage(string message)
      
    {
          MessageBox.Show(message);     
       }
    }

    您也可以按照以下示例所演示的那样将
    lambda 表达式分配给 Action<(Of <(T>)>) 委托实例。(有关 lambda 表达式的简介,请参见 Lambda
    表达式(C# 编程指南)。)
    C#
    复制代码

    using System;
    using
    System.Windows.Forms;

    public class TestLambdaExpression
    {
       public
    static void Main()
       {
          Action<string> messageTarget;


          if (Environment.GetCommandLineArgs().Length > 1)
            
    messageTarget = s => ShowWindowsMessage(s);
          else
            
    messageTarget = s => Console.WriteLine(s);

          messageTarget("Hello,
    World!");
       }

       private static void ShowWindowsMessage(string
    message)
       {
          MessageBox.Show(message);     
      
    }
    }

    018hxwa8.alert_note(zh-cn,VS.90).gif说明:

    Visual Basic 要求
    lambda 表达式返回值。因此,在 Visual Basic 中无法将 Action<(Of <(T>)>) 委托与 lambda
    表达式一起使用。

    ForEach 和 ForEach<(Of <(T>)>) 方法都采用 Action<(Of
    <(T>)>) 委托作为参数。通过使用由委托封装的方法,可以对数组或列表中的每个元素执行操作。此示例使用 ForEach
    方法提供说明。
    示例

    下面的示例演示如何使用 Action<(Of <(T>)>) 委托来打印
    List<(Of <(T>)>) 对象的内容。在此示例中,使用 Print 方法将列表的内容显示到控制台上。此外,C#
    示例还演示如何使用匿名方法将内容显示到控制台上。

    C#
    复制代码

    using System;
    using
    System.Collections.Generic;

    class Program
    {
        static void
    Main()
        {
            List<String> names = new
    List<String>();
            names.Add("Bruce");
            names.Add("Alfred");
            names.Add("Tim");
            names.Add("Richard");

            //
    Display the contents of the list using the Print
    method.
            names.ForEach(Print);

            // The following
    demonstrates the anonymous method feature of C#
            // to display the
    contents of the list to the console.
            names.ForEach(delegate(String
    name)
            {
                Console.WriteLine(name);
            });
        }

        private
    static void Print(string
    s)
        {
            Console.WriteLine(s);
        }
    }
    /* This code will
    produce output similar to the following:
    * Bruce
    * Alfred
    * Tim
    *
    Richard
    * Bruce
    * Alfred
    * Tim
    * Richard

    http://www.cnblogs.com/zjw2004112/archive/2009/09/30/csharp-action-t.html




    不能不说的C#特性-匿名方法和Lambda表达式


    在我们程序中,经常有这样一些需求:

    1.
    需要一个临时方法,这个方法只会使用一次,或者使用的很少。

    2.
    这个方法的方法体很短,以至于比方法声明都短,写起来实在没劲(我将其称之为“一句话方法”)。

    没办法,这样的方法写起来真是吃力不讨好,比如一些按钮事件处理中,有些按钮点击就是弹出一个对话框,或者调用一下别的什么方法。比如下面的代码:
    this.btnRefresh.Click
    += new System.EventHandler(this.btnRefresh_Click);
    private void
    btnRefresh_Click(object sender, EventArgs
    e)
    {
        BindData();
    }

    这个”Refresh”按钮就是做一下调用一下BindData()数据绑定的方法,为此我们不得不写一个新方法。好了,C#
    2.0为我们提供了匿名方法:
    this.btnRefresh.Click += delegate(object sender, EventArgs e)
    { BindData();
    };

    没劲的代码没了。想知道这种写法的幕后黑手么?

    其实编译器还是在我们的后面干了一件龌龊的事情:它为我们产生了一个新的方法,它只是表面上为我们节省了代码。
    privatevoidb__0(object
    sender, EventArgs
    e)
    {
        this.BindData();
    }

    看看这个编译器产生的方法的名称:

    b_0,Test是这个匿名方法所放置的地方(因为这个按钮的时间我是放在一个Test方法里的)
    还有一点需要注意的是,如果这个匿名方法是在实例方法里使用,那么编译器为我们生成的幕后方法也是实例方法,否则就是静态方法了。

    是不是觉得匿名方法这东西很不错,减少了很多代码阿,但是匿名方法的使用还并不人性化,什么是人性化呢?比如你可以用自然的语言将程序代码读出来,
    这样才算人性化了.在.net
    2.0中System.Collections.Generic命名空间下List里有一些新增的方法。比如Find,如果使用匿名方法我们如何调用呢:
    books.Find(delegate(Book
    book){return book.Price <
    50;});

    代码是很简单,但是却无法朗读出来,来看看Lambda表达式的写法:

    books.Find(book=>book.Price<50);这个Lambda表达式就可以这样阅读出来了:给你一本书,如果它的价格小于50则返回true。

    好了,那我们就走进Lambda表达式吧:

    将使用了Lambda表达式的程序集反编译后,我们发现,它实际上和匿名方法没有什么不同。Lambda的输入参数就对应着delegate括号里面的参数,由于Lambda表达式可以推断参数的类型,所以这里的参数无需声明。

    Lambda操作符读作”Goes
    to”,它后面紧跟着表达式或者是语句块(这点和匿名方法也不同,匿名方法只能使用语句块而不能使用表达式),下面我就用实例来说明一下有那些类型的Lambda表达式:

    //x的类型省略了,编译器可以根据上下文推断出来,后面跟着的是表达式
    //x的类型省略了,编译器可以根据上下文推断出来,后面跟着的是表达式
    x
    => x+1
    deleage(int x){return x+1;}
    //后面跟着的是语句块
    x=>{return
    x+1;}
    delegate(int x){return x+1;}
    //输入参数也可以带类型,带类型后别忘记小括号哦
    (int x)
    => x+1
    delegate(int x){return x+1;}
    //也可以多个输入参数,逗号分隔,别忘记小括号
    (x,y)
    => x+y
    delegate(int x,int y){return x+y;}
    //无参的也行

    () =>
    1

    delegate(){return
    1;}

    对于Lambda表达式来说她的用法就是如此,但是在Lambda背后却有很多的故事和玄机。用Lambda表达式可以构建表达式树,而表达式树对于Linq来说就像树根对于树一样重要。在这里就不讨论表达式树的问题了,这个东西也不是三言两语能够说清楚的,等待时机成熟的时候我们再来进一步讨论。
    Lambda表达式更多阅读

    Lambda实际上源远流长,我们现在使用的机器都是冯-诺依曼体系的,属于图灵机,在那之前还有一种称作λ演算的理论,但是图灵机由于先被实现出来,所以大行其道,λ演算后来成就了函数式编程语言特别是Lisp,在函数式编程语言里函数是第一等元素,函数的参数,函数的返回值都是函数,程序没有变量,函数嵌套函数。而且函数式编程语言一直存在于象牙塔中,所以在工业界并没有得到通用,不过近年来工业界比较喜欢“复古”风格,所以函数式编程语言也慢慢的走上了历史的舞台。函数式编程能解决一些命令式编程难以解决的问题(或者解决起来非常麻烦)。C#要做到函数风格编程怎么办?靠原来的方法定义的方式肯定是不可行的,2.0的匿名方法从某种程序上来说解决了这个问题,但还是不够,3.0里的Lambda终于很好的解决了,一个Lambda就是一个
    delegate,一个delegate指向一个方法,现在我们使用Lambda也能简单的将方法作为参数传递了,还可以层层嵌套,都是很简单的事情了。
  • 相关阅读:
    封装成帧、帧定界、帧同步、透明传输(字符计数法、字符串的首尾填充法、零比特填充的首尾标志法、违规编码法)
    计算机网络之数据链路层的基本概念和功能概述
    物理层设备(中继器、集线器)
    计算机网络之传输介质(双绞线、同轴电缆、光纤、无线电缆、微波、激光、红外线)
    计算机网络之编码与调制
    0953. Verifying an Alien Dictionary (E)
    1704. Determine if String Halves Are Alike (E)
    1551. Minimum Operations to Make Array Equal (M)
    0775. Global and Local Inversions (M)
    0622. Design Circular Queue (M)
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/2629838.html
Copyright © 2020-2023  润新知