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也能简单的将方法作为参数传递了,还可以层层嵌套,都是很简单的事情了。

[转载]C#基础-Func,Action的更多相关文章

  1. C#基础-Func,Action

    Func,Action 的介绍及其用法 Func是一种委托,这是在3.5里面新增的,2.0里面我们使用委托是用Delegate,Func位于System.Core命名空间下,使用委托可以提升效率,例如 ...

  2. C# Task中的Func, Action, Async与Await的使用

    在说Asnc和Await之前,先说明一下Func和Action委托, Task任务的基础的用法 1. Func Func是一种委托,这是在3.5里面新增的,2.0里面我们使用委托是用Delegate, ...

  3. 浅谈C#中常见的委托<Func,Action,Predicate>(转)

    一提到委托,浮现在我们脑海中的大概是听的最多的就是类似C++的函数指针吧,呵呵,至少我的第一个反应是这样的. 关于委托的定义和使用,已经有诸多的人讲解过,并且讲解细致入微,尤其是张子阳的那一篇.我就不 ...

  4. [转]C# ListView 单击标题实现排序(在转载的基础上有所完善)

    using System; using System.Collections; using System.Windows.Forms; //在转载的基础上有所完善 namespace TDRFacto ...

  5. 关于 wpf 的ICommand 的 CanExecute CanExecuteChanged func action的认识

    关于 wpf 的ICommand 的 CanExecute CanExecuteChanged  func  action的认识

  6. [C#基础]Func和Action学习

    目录 委托 Action Func 总结 委托 委托的那些事 关于委托的基本定义,在很久之前的这篇文章中,有个简单的介绍.稍微回顾一下. 委托是c#中类型安全的,可以订阅一个或多个具有相同签名方法的函 ...

  7. C#基础——Func和Action的介绍及其用法

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

  8. 泛型委托 Predicate/Func/Action

    Predicate 泛型委托  表示定义一组条件并确定指定对象是否符合这些条件的方法.此委托由 Array 和 List 类的几种方法使用,用于在集合中搜索元素.看看下面它的定义: // Summar ...

  9. C#的泛型委托Predicate/Func/Action(转)

    Predicate 泛型委托:表示定义一组条件并确定指定对象是否符合这些条件的方法.此委托由 Array 和 List 类的几种方法使用,用于在集合中搜索元素. 类型参数介绍:    T: 要比较的对 ...

随机推荐

  1. couldnt resolve host mirrorlist.centos

     解决centos 6.3 yum安装软件时找不到镜像问题 [root@nagios-server ~]# yum update –y Loaded plugins: fastestmirror Lo ...

  2. BZOJ 1588 营业额统计 Splay

    主要操作为Splay中插入节点,查找前驱和后继节点. 1: #include <cstdio> 2: #include <iostream> 3: #include <c ...

  3. java优化占用内存的方法(一)

    java做的系统给人的印象是什么?占 内存!说道这句话就会有N多人站出来为java辩护,并举出一堆的性能测试报告来证明这一点.其实从理论上来讲java做的系统并不比其他语言开发出来的 系统更占用内存, ...

  4. 浏览器对象模型BOM(Browser Object Model)

    1.结构 BOM是Browser Object Model的缩写,简称浏览器对象模型 BOM提供了独立于内容而与浏览器窗口进行交互的对象 由于BOM主要用于管理窗口与窗口之间的通讯,因此其核心对象是w ...

  5. Mybatis 示例之 SelectKey(转)

    参考:http://blog.csdn.net/isea533/article/details/21153791 SelectKey在Mybatis中是为了解决Insert数据时不支持主键自动生成的问 ...

  6. 【概率】poj 2096:Collecting Bugs

    Description Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other ...

  7. What are the advantages of logistic regression over decision trees?FAQ

    What are the advantages of logistic regression over decision trees?FAQ The answer to "Should I ...

  8. PAT-乙级-1001. 害死人不偿命的(3n+1)猜想 (15)

    1001. 害死人不偿命的(3n+1)猜想 (15) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 卡拉兹(Ca ...

  9. Good Bye 2015B

    Problem B:http://codeforces.com/contest/611/problem/B B. New Year and Old Property 题意:问输入的年份a到b中转化为二 ...

  10. Otto开发初探——微服务依赖管理新利器

    [编者按]时下,Vagrant 被 DevOps 软件开发商广泛作为开发阶段的本地软件开发环境,而在本文,CERT Division高级研究员介绍的 Otto 则是 Vagrant 开发团队 Hash ...