关于c#中委托使用小结
一、简述:
委托对与我们编程人员来说,一点都不陌生,在实际工作过程中,或多或少都应该是接触过
但是对与编程新手来说,对与委托的理解和使用应该还是一个坎,但是只要理解清楚了,这个坎也就过去了。
最近也经常有人在问关于委托的使用的相关问题,在此我花点时间,对与委托的个人理解进行一个总结,希望能够给大家有所帮助作用。
二、定义:
委托,其实在我们日常生活中,也经常用到委托的,比如:律师其实就是充当了一个委托的角色,当事人委托律师在法庭上对其诉讼辩护。
在c#中,委托简单的理解就是将一个方法以参数的形式传递到另外一个方法中去,有点类似于c++中的指针的概念。
三、实现委托的步骤:
在委托定义的时候,我们只需要定义一个结构体,至于具体的实现,需要在具体的委托方法中来实现。
实现委托的步骤,我总结如下:
其一、定义:要声明一个委托的结构体:delegate void Mydelegate(type1 para1,type2 para2);
其二、声明:声明就是要声明一个委托变量:Mydelegate myDel;
其三、实例化:就是要对声明的委托对象实例化具体的委托方法:myDel=new Mydelegate(obj.InstanceMethod);
其四、参数传递:简单的理解,就是将委托以一个参数的形式传递给一个方法:MyMethod(myDel);
其五、委托方法执行:这个和普通方法实现调用一样,就是在方法MyMethod里面调用执行委托的方法:myDel(obj.InstanceMethod)
四、使用
委托的使用,根据平时的开经验,委托其实在实际的使用中,有两种场景:
其一、同步使用:同步执行委托,阻塞主流程(和平时的方法执行效果一样)
namespace MyCalculat
{
/// <summary>
/// 定义一个委托
/// </summary>
/// <param name="num1">阐述1</param>
/// <param name="num2">参数2</param>
/// <returns>处理结果</returns>
public delegate int MyDelegate(int num1, int num2); /// <summary>
/// Calculat类
/// </summary>
public class Calculat
{
public int Calcul(int num1,int num2,int type ) {
MyDelegate myDelegate;
switch (type) {
case :
myDelegate = new MyDelegate(this.Add);
break;
case :
myDelegate = new MyDelegate(this.Reduce);
break;
////
//// 其他逻辑
////
default:
myDelegate = new MyDelegate(this.Add);
break;
}
return this.CalculOpert(myDelegate,num1, num2);
} /// <summary>
/// 计算具体逻辑处理
/// </summary>
/// <param name="calDel">MyDelegate计算委托变量</param>
/// <param name="num1">参数1</param>
/// <param name="num2">参数2</param>
/// <returns>计算处理结果</returns>
public int CalculOpert(MyDelegate calDel, int num1, int num2)
{
////
//// 其他业务逻辑处理
//// //// 委托调用处理--同步调用
return calDel.Invoke(num1,num2);
} /// <summary>
/// 相加
/// </summary>
/// <param name="num1">参数1</param>
/// <param name="num2">参数2</param>
/// <returns>结果</returns>
public int Add(int num1, int num2) {
return num1 + num2;
} /// <summary>
/// 相法
/// </summary>
/// <param name="num1">参数1</param>
/// <param name="num2">参数2</param>
/// <returns>结果</returns>
public int Reduce(int num1, int num2)
{
return num1 - num2;
}
}
}
其二、异步使用:不阻塞主流程的执行,异步线程去执行委托方法里面的逻辑
namespace MyCalculat
{
/// <summary>
/// 定义一个委托
/// </summary>
/// <param name="num1">阐述1</param>
/// <param name="num2">参数2</param>
/// <returns>处理结果</returns>
public delegate int MyDelegate(int num1, int num2); /// <summary>
/// Calculat类
/// </summary>
public class AcyCalculat
{
public void Calcul(int num1, int num2, int type)
{
MyDelegate myDelegate;
switch (type)
{
case :
myDelegate = new MyDelegate(this.Add);
break;
case :
myDelegate = new MyDelegate(this.Reduce);
break;
////
//// 其他逻辑
////
default:
myDelegate = new MyDelegate(this.Add);
break;
} this.CalculOpert(myDelegate,num1,num2) ;
} /// <summary>
/// 计算具体逻辑处理
/// </summary>
/// <param name="calDel">MyDelegate计算委托变量</param>
/// <param name="num1">参数1</param>
/// <param name="num2">参数2</param>
/// <returns>计算处理结果</returns>
public void CalculOpert(MyDelegate calDel, int num1, int num2)
{
////
//// 其他业务逻辑处理
//// //// 委托调用处理--异步调用 //// 异步执行完毕后,无需回调方法
calDel.BeginInvoke(num1, num2, null, null);
//// 异步执行完毕后,有回调方法
calDel.BeginInvoke(num1, num2, new AsyncCallback(this.AsyncOpert), new int[] { num1, num2 }); } /// <summary>
/// 处理异步执行结果逻辑
/// </summary>
/// <param name="resout">异步处理结果</param>
public void AsyncOpert(IAsyncResult resout)
{
MyDelegate myDel = (MyDelegate)((AsyncResult)resout).AsyncDelegate;
//// 获取异步处理结果
int res = myDel.EndInvoke(resout); //// 委托方法参数
int[] lisNum = (int[])resout.AsyncState; if (res > )
{
/////
///// 业务逻辑处理
/////
}
else
{
/////
///// 业务逻辑处理
/////
}
} /// <summary>
/// 相加
/// </summary>
/// <param name="num1">参数1</param>
/// <param name="num2">参数2</param>
/// <returns>结果</returns>
public int Add(int num1, int num2)
{
//// 其它业务逻辑处理
return num1 + num2;
} /// <summary>
/// 相法
/// </summary>
/// <param name="num1">参数1</param>
/// <param name="num2">参数2</param>
/// <returns>结果</returns>
public int Reduce(int num1, int num2)
{
//// 其它业务逻辑处理
return num1 - num2;
}
}
}
委托结合反射的使用:这中情况的使用场景是:当不同的委托其对于的参数个数或者参数类型不尽相同,那么这时候就在调用委托方法时,就不能简简单单的调用执行
这种情况在实际工作中场景举例:比如我们在使用缓存机制时候,都要使用到委托通反射相结合使用。
/// <summary>
/// Calculat类
/// </summary>
public class Calculat
{
/// <summary>
/// 获取产品详情
/// </summary>
/// <param name="proKeyID">产品ID</param>
/// <returns>获取结果</returns>
public string GetProInfor(string proKeyID)
{
string proInfor = string.Empty; proInfor = ChachHelp.GetBusData<string>(new Func<string, string>(new ProBuss().GetProInfor), "proDetile" + proKeyID, , proKeyID); return proInfor;
} /// <summary>
/// 获取用户常用产品
/// </summary>
/// <param name="userID">用户ID</param>
/// <param name="cout">获取条数</param>
/// <returns>获取结果</returns>
public string GetCommonProInto(string userID, int cout)
{
string commonProInto = string.Empty; commonProInto = ChachHelp.GetBusData<string>(new Func<string, int, string>(new ProBuss().GetCommonProInto), "commonProInto" + userID, , userID, cout); return commonProInto;
}
} /// <summary>
/// 产品相关操作的业务逻辑处理
/// </summary>
public class ProBuss
{
/// <summary>
/// 获取产品详情
/// </summary>
/// <param name="proKeyID">产品ID</param>
/// <returns>获取结果</returns>
public string GetProInfor(string proKeyID)
{
string proInfor = string.Empty; ////---
//// 具体产品详情的逻辑处理
///--- return proInfor;
} /// <summary>
/// 获取用户常用产品
/// </summary>
/// <param name="userID">用户ID</param>
/// <param name="cout">获取条数</param>
/// <returns>获取结果</returns>
public string GetCommonProInto(string userID, int cout)
{
string commonProInto = string.Empty; ////---
//// 获取用户常用产品的逻辑处理
///--- return commonProInto;
}
} /// <summary>
/// 缓存操作类
/// </summary>
public class ChachHelp
{
/// <summary>
/// 获取缓存方法
/// </summary>
/// <typeparam name="T">返回数据类型</typeparam>
/// <param name="dele">数据获取方法</param>
/// <param name="cacheKey">缓存建</param>
/// <param name="cacheDuration">缓存时间</param>
/// <param name="objs">具体的参数集合</param>
/// <returns>获取结果</returns>
public static T GetBusData<T>(Delegate dele, string cacheKey, int cacheDuration, params object[] objs)
{
object obj = null; try
{
///// obj =//// 具体调用缓存获取数据方法;
}
catch (Exception ex)
{
//// 吃掉异常
} //// 如果缓存中没有获取到数据,那么就直接通过方法获取数据
if (obj == null)
{
string assemblyName = dele.Target.GetType().Assembly.FullName;
string typeName = dele.Target.GetType().FullName;
object instance = Assembly.Load(assemblyName).CreateInstance(typeName);
MethodInfo methodInfo = dele.Method; obj = methodInfo.Invoke(instance, objs);
if (obj != null)
{
//// 在获取到数据后,应当将获取到数据,存储记得到缓存中去
//// 缓存存储具体方法逻辑
}
} //// 类型转换,将obj转换为对应的数据类型
//// 此处先简略的直接用强制转换一波
T tobj = (T)obj;
return tobj;
}
}
五、小结:
从上面的委托代码中可以发现,引入委托后,编程人员可以把方法的引用封装在委托对象中
(把过程的调用转化为对象的调用,充分体现了委托加强了面向对象编程的思想。),
然后把委托对象传递给需要引用方法的代码,这样在编译的过程中我们并不知道调用了哪个方法,
这样一来,C#引入委托机制后,使得方法声明和方法实现的分离,充分体现了面向对象的编程思想。
关于c#中委托使用小结的更多相关文章
- C#不用union,而是有更好的方式实现 .net自定义错误页面实现 .net自定义错误页面实现升级篇 .net捕捉全局未处理异常的3种方式 一款很不错的FLASH时种插件 关于c#中委托使用小结 WEB网站常见受攻击方式及解决办法 判断URL是否存在 提升高并发量服务器性能解决思路
C#不用union,而是有更好的方式实现 用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C# ...
- 详解Objective-C中委托和协议
Objective-C委托和协议本没有任何关系,协议如前所述,就是起到C++中纯虚类的作用,对于“委托”则和协议没有关系,只是我们经常利用协议还实现委托的机制,其实不用协议也完全可以实现委托. AD: ...
- MVC图片上传详解 IIS (安装SSL证书后) 实现 HTTP 自动跳转到 HTTPS C#中Enum用法小结 表达式目录树 “村长”教你测试用例 引用provinces.js的三级联动
MVC图片上传详解 MVC图片上传--控制器方法 新建一个控制器命名为File,定义一个Img方法 [HttpPost]public ActionResult Img(HttpPostedFile ...
- C#中委托和事件的区别实例解析
这篇文章主要介绍了C#中委托和事件的区别,并分别以实例形式展示了通过委托执行方法与通过事件执行方法,以及相关的执行流程与原理分析,需要的朋友可以参考下 本文实例分析了C#中委托和事件的区别,分享给大家 ...
- C#中委托和事件
目 录 将方法作为方法的参数 将方法绑定到委托 更好的封装性 限制类型能力 范例说明 Observer 设计模式简介 实现范例的Observer 设计模式 .NET 框架中的委托与事件 为什么委托定义 ...
- c#中委托和事件(转)
C# 中的委托和事件 引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真 ...
- C#中委托
委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似.与 C 中的函数指针不同,委托是面向对象的.类型安全的和保险的.一个委托类型是代表与特定参数列表和返回类型的方法的引用类型.实例 ...
- C#中委托的理解
请注意,这只是个人关于C#中委托的一点点理解,参考了一些博客,如有不周之处,请指出,谢谢! 委托是一种函数指针,委托是方法的抽象,方法是委托的实例.委托是C#语言的一道坎,明白了委托才能算是C#真正入 ...
- 180531-Spring中JavaConfig知识小结
原文链接:Spring中JavaConfig知识小结/ Sring中JavaConfig使用姿势 去掉xml的配置方式,改成用Java来配置,最常见的就是将xml中的 bean定义, scanner包 ...
随机推荐
- Hibernate4.x之映射关系--单向一对多
在领域模型中,类与类之间最普遍的关系就是关联关系在UML中,关联是有方向的 以Customer和Order为例:一个用户能发出多个订单,而一个订单只能属于一个客户.从Order到Customer的关联 ...
- 20个非常绚丽的 CSS3 特性应用演示
这篇文章收集了20个非常绚丽的 CSS3 效果应用演示,这些示例演示了 CSS3 各种新特性的强大能力.随着越来越多的浏览器对 CSS3 支持的不断完善,设计师和开发者们有了更多的选择,以前需要使用 ...
- MVC 5 的 EF6 Code First 入门
英文渣水平,大伙凑合着看吧…… 这是微软官方SignalR 2.0教程Getting Started with Entity Framework 6 Code First using MVC 5 系列 ...
- [转] Envelop
xiaohaidepoli原文Envelop Envelope也称包络线,是一个矩形区域,是每个几何形体的最小外接矩形.每个Geometry都拥有一个Envelope,包括Envelope自身. 它定 ...
- opencv 在工业中的应用:二维标定
在工业中经常要检测一个零件的尺寸,但是图像处理得到的是像素值,怎么才能得到实际的毫米值呢?这就要用到二维标定,我用OPENCV写了一个利用标定板进行标定的DEMO. 很多商业软件都没有二维标定的功能, ...
- 【暑假】[实用数据结构]UVAlive 3942 Remember the Word
UVAlive 3942 Remember the Word 题目: Remember the Word Time Limit: 3000MS Memory Limit: Unknown ...
- USB模式安装CentOS6.4_minimal
首先说明一下我遇到的3个问题 1. 由于机器没有光驱,所以只能USB安装 2.由于CentOS5.0+才对USB安装支持比较好,所以USB安装,建议安装CentOS5.0+以上的版本 3.由于FAT3 ...
- openstack api
1,Identity service generates authentication tokens that permit access to the openstack service REST ...
- hdu4777-Rabbit Kingdom
题意:求区间内与其他任何数都互质的数的个数. 题解:求出每个数左右互质的边界.然后对询问排序,通过树状数组求解. 讲道理真的好难啊= = http://blog.csdn.net/dyx404514/ ...
- Codeforces Round #138 (Div. 2) ACBDE
A.Parallelepiped 题意:给一个六面体三面的面积,求12条边的长度和. 题解:因为都是整数,设边长分别为a,b,c,面积为xyz,那么可设x=a*b,y=b*c,z=c*a,简单解方程就 ...