C#4.0推出后,类似Linq,Lamda表达式等许多新的程序写法层次不穷。与之相关的Delegate,Action,Func,Predicate的使用和区别也常常让大家迷惑,此处就结合实际的应用,对其进行详细的说明。

在书写代码时,常常会用到委托,这个在winform下较常见,但自定义Delegate时,我们常常发现Delegate必须全局可见,才能在需要的地方进行使用,而对于私有的delegate对象,在本类中进行使用,这似乎是不方便的。下边我们来看传统的Delegate的写法。

public delegate void MyDelegate(string name);
    public class MyBlogBase
    {
        private MyDelegate mydelegate;
    }
 

必须保证MyDelegate放在类的外边,才能在其他地方可见,并使用,Action,Func的出现改变了这一局面,这两个其实说白了就是系统定义好的Delegate,他有很多重载的方法,便于各种应用情况下的调用。他在系统的System命名空间下,因此全局可见。下文就说明Action,Action有多个重载,下文已Action<T>为例进行说明

Action<T>:封装一个方法,该方法只有一个参数并且不返回值。其中T是可接收的任何类型。使用代码如下:


public class MyBlogBase
    {   
        public string myName;
        Action<string> myAction;   
        public MyBlogBase()
        {
            //myAction = delegate(string curName) { myName = curName; };
            //myAction = new Action<string>(SetAction);
            myAction = curname => { myName = curname; };
          
        }
        private void SetAction(string name)
        {
            myName = name;
        }
    }

在上例中,给出了3种使用Action的方法,方法一:采用匿名委托,方法二:指定一个实际的方法。方法三:使用Lamda表达式。以上3中用法均可运行。

在实际应用中要比原始的定义Delegate方便,灵活。那么Func呢?

Func<T in,T Tresult>:封装一个具有一个参数并返回 TResult 参数指定的类型值的方法。其实个人感觉,Func和Action的区别很明显,也很直接。二者都是委托,但Func能返回函数执行结果,而Action返回类型是Void,这个区别很明显,在具体的项目中,也很容易确定该使用那个。下文就说明具体Func的代码调用:


public string myName;
        Func<string, string> myFunc;    
        public MyBlogBase()
        {          
            //myFunc = delegate(string curName) { return curName.ToUpper(); };
            //myFunc = new Func<string, string>(SetFunc);
            myFunc = name => { return name.ToUpper(); };       
        }     
        private string SetFunc(string name)
        {
            return name.ToUpper();
        }      
        public void StartFun(string curName)
        {
            myName = myFunc(curName);
        }

如上3种写法,都是合适的Func定义,大家可以选择适合自己的编程模式,其实匿名方法,有个优点,就是可以直接使用当前函数出现的变量,代码更简洁,但可能有些人觉得不易读。

Predicate<T>:也是一种委托,表示定义一组条件并确定指定对象是否符合这些条件的方法.此方法常在集合的查找中被用到,如:数组,正则拼配的结果集中被用到。使用此方法快捷方便,使用代码如下:


Predicate<int> myPredicate;
        int[] myNum = new int[8] { 12, 33, 89, 21, 15, 29, 40, 52 };
       public int[] myResult;
        public MyBlogBase()
        {
            myPredicate = delegate(int curNum)             { if (curNum % 2 == 0) return true;               else return false;             };
        } 
        public void StartPredicate()
        {
            myResult = Array.FindAll(myNum, myPredicate);
        }
 

上例中说明了Predicate的使用,FindAll方法中,参数2即是一个Predicate,在具体的执行中,每一个数组的元素都会执行指定的方法,如果满足要求返回true,并会被存放在结果集中,不符合的则被剔除,最终返回的集合,即是结果判断后想要的集合,此方法应用场景感觉像迭代中的yield。当然此方法也可以书写上边类似Action和Func的3中方式,此处省略。

为了更好的验证运行效果,添加Test项目及进行测试,把代码粘帖出来分享一下:


[TestMethod]
        public void TestAction()
        {
            MyBlogBase blogObj = new MyBlogBase();
            blogObj.StartAction("ywg369");
            Assert.AreEqual("ywg369", blogObj.myName);
        }
        [TestMethod]
        public void TestFunc()
        {
            MyBlogBase blogObj = new MyBlogBase();
            blogObj.StartFun("ywg369");
            Assert.AreEqual("YWG369", blogObj.myName);
        }
        [TestMethod]
        public void TestPredicate()
        {
            MyBlogBase blogObj = new MyBlogBase();
            blogObj.StartPredicate();
            Assert.AreEqual(3, blogObj.myResult.Length);
        }

经过验证,运行良好,各个方法都按照期望的结果运行成功。通过此处对Delegate,Action,Func,Predicate的使用有个大致的了解,在具体的应用中根据

实际情况进行调用。大家对此有什么好的建议或意见,多交流。

其实他们两个都是委托【代理】的简写形式。

 
一、【action<>】指定那些只有输入参数,没有返回值的委托
 
Delegate的代码:
 
[csharp] 
public delegate void myDelegate(string str); 
public static void HellowChinese(string strChinese) 
Console.WriteLine("Good morning," + strChinese);
    Console.ReadLine(); 
 
myDelegate d = new myDelegate(HellowChinese); 
d("Mr wang"); 
 
用了Action之后呢:
 
 
 
[csharp] 
public static void HellowChinese(string strChinese) 
    Console.WriteLine("Good morning," + strChinese); 
    Console.ReadLine(); 
 
Action<string> action = HellowChinese; 
action("Spring."); 
就是相当于省去了定义委托的步骤了。
 
 
 
二、func<> 这个和上面的那个是一样的,区别是这个有返回值!
 
[csharp]  www.2cto.com
public static string HelloEnglish(string strEnglish) 
    return "Hello." + strEnglish; 
 
Func<string, string> f = HelloEnglish; 
Console.WriteLine(f("Srping ji")); 
Console.ReadLine(); 
 
 

Func委托

封装一个带有返回 TResult 参数指定的类型值的方法,它有5个重载:

·Func<TResult>

·Func<T,TResult>

·Func<T1,T2,TResult>

·Func<T1,T2,T3,TResult>

·Func<T1,T2,T3,T4,TResult>

这里用一个举例说明:以Func<T,TR>这个来说明。这个从根源讲要说到委托(delegate)。这个方法的意义是有一个T参数,且返回值类型为TR类型的方法。

(1)按常规来做的方法为

定义一个返回bool的方法。

public bool IsTen(int i)
{    
  return i == 10 ? true : false;
}

测试

[Test]
public void TestFun1()
{    
  Assert.AreEqual(true, IsTen(10));
}

(2)通过委托来实现

 
delegate bool IsTenDelegate(int i);
public bool IsTen(int i)
{    
  return i == 10 ? true : false;
}
[Test]
public void TestFun1()
{    
  //IsTenDelegate d = IsTen;    
  IsTenDelegate d = new IsTenDelegate(IsTen);    
  Assert.AreEqual(true, d(10));
}
 

这里把方法IsTen委托给了委托类型IsTenDelegate 。以下是2.0中匿名方法的实现

(3)匿名方法

 
[Test]
public void TestFun1()
{   
  IsTenDelegate  d= delegate(int i)    
  {       
    return i == 10 ? true : false;    
  };
    Assert.AreEqual(true, d(10));
}
 

通过匿名方法内联方式实现了委托IsTenDelegate  。然后在3.*版本中,通过lambda表达式成为内联委托的首选方法

(4)Lambda

 
[Test]
public void TestFun1()
{    
  IsTenDelegate d = x => x == 10 ? true : false;    
  Assert.AreEqual(true, d(10));
}
 

关于Lambda的内容请见我的另一篇随笔:

http://www.cnblogs.com/jams742003/archive/2009/12/23/1630737.html

(5)Func<T>

public delegate TResult Func<TResult>()

这里Func<T>的方法定义,它是一个delegate,所以,上边的IsTenDelegate 委托可以写成:

Func<int, bool> d = x => x == 10 ? true : false;
Assert.AreEqual(true, d(10));

这就是Func,它带有返回值,且有5种重载,可以委托0-4个参数的方法。

而Action<T>则与Func意义相近,只是不带返回值。

Action委托

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

Action

Action<T>

Action<T1,T2>

Action<T1,T2,T3>

Action<T1,T2,T3,T4>

Delegate,Action,Func,Predicate的使用与区别的更多相关文章

  1. C# 委托应用总结(委托,Delegate,Action,Func,predicate)

    C# 委托应用总结 一.什么是委托 1.1官方解释 委托是一种定义方法签名的类型.当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联.您可以通过委托实例调用方法. 1.2个人理解 委托就是执 ...

  2. 委托delegate,Action,Func,Predicate

    C#委托的介绍(delegate.Action.Func.predicate) 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递.事件是一种特殊的委托. 1.委托的声明 ...

  3. (C#) Action, Func, Predicate 等泛型委托

    (转载网络文章) (1). delegate delegate我们常用到的一种声明   Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型.   例:public del ...

  4. Delegate,Action,Func,匿名方法,匿名委托,事件 (转载)

    Delegate,Action,Func,匿名方法,匿名委托,事件 (转载) 一.委托Delegate 一般的方法(Method)中,我们的参数总是string,int,DateTime...这些基本 ...

  5. c# Action,Func,Predicate委托

    System命名空间下已经预先定义好了三中泛型委托,Action,Func和Predicate,这样我们在编程的时候,就不必要自己去定义这些委托了 Action是没有返回值的 Func是带返回值的 不 ...

  6. 【Unity|C#】基础篇(11)——内置的泛型委托(Action/Func/Predicate)

    [Action] 无返回值 的泛型委托,可以有0~16个参数(函数重载) public delegate void Action(); // 无参数 public delegate void Acti ...

  7. Delegate,Action,Func,匿名方法,匿名委托,事件

    一.委托Delegate 一般的方法(Method)中,我们的参数总是string,int,DateTime...这些基本的数据类型(或者没有参数),比如 public void HelloWorld ...

  8. 温故而知新:Delegate,Action,Func,匿名方法,匿名委托,事件

    Tks: http://www.cnblogs.com/yjmyzz/archive/2009/11/23/1608818.html 20150801 add: http://www.cnblogs. ...

  9. .NET自带泛型委托方法Func、Action和Predicate

    Func.Action和Predicate是.NET自带的3个泛型委托方法,三个方法的区别其实并不大,要强行给混着用也是可以的,但是我们是有追求的人,把道理讲清楚总是好的. 一.Func是有返回值的方 ...

随机推荐

  1. CareerCup chapter 1 Arrays and Strings

    1.Implement an algorithm to determine if a string has all unique characters What if you can not use ...

  2. 进程和线程之间的关系和区别 和 CPU牒

    流程具有一定独立功能的程序关于某个数据集合上的一次执行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立执行的基本单位. 进 ...

  3. OOP思想

    OOP思想 读者朋友们大家好,我们今天这一讲就接着前面的封装继续讲解,今天就是在前面内容上面的升级,OOP思想中的继承,我们就先来解释一下继承到底是什么意思,我们在什么地方会用到继续. 继承就是,后代 ...

  4. 集差集 哈希表 比较数据库的照片和server画面上,将server垃圾上的图片删除

    SSH 骨架code: public String deleRubbishAd(){ int deleADcount = 0; rubbishADtp = configDao.rubbishADtp( ...

  5. Java新手入门的30个基本概念

    Java已经成为一个庞大而复杂的技术平台,对于开发者而言,特别是刚開始学习的人,要想更好的掌握Java技术,深入理解基本概念不可缺少,能够帮助你提高对Java的进一步了解.以下为你介绍了Java语言的 ...

  6. 【cocos2d-x】尝鲜 Cocos Code IDE(不断更新)

    Cocos Code IDE 是一个基于 Eclipse 的跨平台 IDE ,专门为 cocos2d lua & js 开发者准备,通过此工具.你能够方便的创建游戏project.编写而且调试 ...

  7. Cocos2d-X 使用CCTableView创建滚动视图

    CCTableView和CCScrollView如创建滚动视图,CCTableView该函数将是更,制造更多麻烦 实例1:使用CCTableView创建滚动视图 首先创建一个TableView类 Ta ...

  8. Unity3D-RPG项目实战(1):发动机的特殊文件夹

    前言 从8月份開始.下定决心正式開始学习Unit3D啦.尽管自己写过两代端游引擎,被应用的项目也超过10个,Unreal Engine也搞过几年,只是做手游.哥确实还是个新手.Unity3D这个引擎我 ...

  9. design pattern Builder 生成器设计模式

    其实设计模式可以学习很有趣,你并不需要有这么难啃旱地FOG对我来说,当然,这些都是健康的骨骼啃啃. 在本文中,建造者模式设计一个搞笑的一幕.根据这一模型来学习功夫的方法,哈哈. 基类的第一,设计.那么 ...

  10. Android属于查询执行情况的电话号码

    这部分是昨天学习,但是因为眼所以现在到眼睛超负荷,以后要合理规划时间. 现在里面的手机号码归属地查询主要通过两种途径:1.网络查询.2.匹配本地归属地数据库. 我认为最好的两个方法的结合,在进行联网查 ...