Delegate,Action,Func,Predicate的使用与区别
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的使用有个大致的了解,在具体的应用中根据
实际情况进行调用。大家对此有什么好的建议或意见,多交流。
其实他们两个都是委托【代理】的简写形式。
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的使用与区别的更多相关文章
- C# 委托应用总结(委托,Delegate,Action,Func,predicate)
C# 委托应用总结 一.什么是委托 1.1官方解释 委托是一种定义方法签名的类型.当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联.您可以通过委托实例调用方法. 1.2个人理解 委托就是执 ...
- 委托delegate,Action,Func,Predicate
C#委托的介绍(delegate.Action.Func.predicate) 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递.事件是一种特殊的委托. 1.委托的声明 ...
- (C#) Action, Func, Predicate 等泛型委托
(转载网络文章) (1). delegate delegate我们常用到的一种声明 Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型. 例:public del ...
- Delegate,Action,Func,匿名方法,匿名委托,事件 (转载)
Delegate,Action,Func,匿名方法,匿名委托,事件 (转载) 一.委托Delegate 一般的方法(Method)中,我们的参数总是string,int,DateTime...这些基本 ...
- c# Action,Func,Predicate委托
System命名空间下已经预先定义好了三中泛型委托,Action,Func和Predicate,这样我们在编程的时候,就不必要自己去定义这些委托了 Action是没有返回值的 Func是带返回值的 不 ...
- 【Unity|C#】基础篇(11)——内置的泛型委托(Action/Func/Predicate)
[Action] 无返回值 的泛型委托,可以有0~16个参数(函数重载) public delegate void Action(); // 无参数 public delegate void Acti ...
- Delegate,Action,Func,匿名方法,匿名委托,事件
一.委托Delegate 一般的方法(Method)中,我们的参数总是string,int,DateTime...这些基本的数据类型(或者没有参数),比如 public void HelloWorld ...
- 温故而知新:Delegate,Action,Func,匿名方法,匿名委托,事件
Tks: http://www.cnblogs.com/yjmyzz/archive/2009/11/23/1608818.html 20150801 add: http://www.cnblogs. ...
- .NET自带泛型委托方法Func、Action和Predicate
Func.Action和Predicate是.NET自带的3个泛型委托方法,三个方法的区别其实并不大,要强行给混着用也是可以的,但是我们是有追求的人,把道理讲清楚总是好的. 一.Func是有返回值的方 ...
随机推荐
- Heibernate 入门笔记(一)---第一个demo
最近在学heibernate,是看马士兵老师的视频学的,在这里总结一下,做点笔记.关于heibernate的优点,大家可以在网上 百度,这里不做赘述,直接讲怎么使用heibernate 步骤一:新建项 ...
- iOS 中client和server的 Web Service 网络通信 (2)
在实际的应用开发过程中,同步请求的用户体验并非非常好:我们都知道.Apple是非常重视用户体验的.这一点也成为了行业的标杆,没实用户哪里来的好产品.所以用户体验是极其重要的.貌似废话有点多.接下来进入 ...
- 微信电脑版(Mac和Windows)安装
内容简介 1.微信Windows版 2.微信Mac版 3.总结优势 微信电脑版 众所周知,腾讯公司(马化腾先生执掌的巨头公司)开发的超成功App:微信.一经推出便引发业界轰动,使用人数更是直逼QQ. ...
- Xaml于string(弦)定义常量和处理空间
xml version="1.0" encoding="UTF-8"? > (1)基本使用方法 xaml中能够实例化各种对象,比方在ResourceDic ...
- AND信号灯和信号灯集-----同步和互斥解决面向对象(两)
AND信号 互斥的上述处理,它是针对仅在进程之间共享的一个关键资源方面.在一些应用.这是一个过程,需要在为了自己的使命后,获得两个或多个其他共享资源运行. 个进程A和B.他们都要求訪问共享数据D和E. ...
- unity3d简单的相机跟随及视野旋转缩放
1.实现相机跟随主角运动 一种简单的方法是把Camera直接拖到Player下面作为Player的子物体,另一种方法是取得Camera与Player的偏移向量,并据此设置Camera位置,便能实现简单 ...
- 房费制 之 登录BUG
声明:以下内容只有当你登录到一个username同时,学生不能申请多次登录. 说是BUG,事实上这也不是一个BUG,仅仅是想出一个办法,解决一个大家好多人都没有解决的问题.以下就给大家 ...
- 从XML文件乱码问题,探寻其背后的原理(转)
由于网友反应本文图片不能显示,由于时间关系未能及时修正.请访问原文地址: 本文出自http://blog.csdn.net/dinglang_2009/article/details/6895355, ...
- TCP与UDP的侵略性
HTTP必须执行在TCP上吗?SSL必须执行在TCP上吗?...实际上HTTP并没有规定一定要执行在TCP上,甚至FTP也不一定要执行在TCP上!HTTP或者FTP仅仅是说底层信道要保证数据的按序传输 ...
- Cocos2d-x3.2游戏的核心循环在Application,怎样处理FPS不稳
今天天气非常阴,立即要下雨了,陈吃早点功夫写点东西, 一场秋雨一场寒,十场秋雨要穿棉,各位从今往后多穿点 int Application::run() { if(!applicationDidFini ...