前言:上一篇介绍了下多线程的相关知识:C#基础系列——多线程的常见用法详解,里面就提到了委托变量。这篇简单介绍下委托的使用。当然啦,园子里面很多介绍委托的文章都会说道:委托和事件的概念就像一道坎,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里发慌。确实这东西就像最开始学C语言的指针一样,令人有一种很纠结的感觉,总觉得要调用一个方法直接调用就行了,为啥非要定义一个委托时执行这个方法呢。其实在C#里面很多的技术都是为了重用和简化代码而生,委托也不例外,很多使用C#多态去实现的设计模式其实都可以使用委托的方式去改写,可以理解为一种轻量级的设计模式吧。博主打算抽一篇专门分享下多态和委托实现设计模式的异同。这篇就先介绍简单委托的使用。

一、什么是委托:C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。用博主的话说,委托就是一种允许将方法名称作为参数传递的引用类型。它定义的是方法的类型,可以说就是方法的抽象,那么反过来说,方法可以理解为委托的实例,如public delegate void TestDelegate(string str);这种委托定义的就是所有参数类型为string,没有返回值的方法的一种抽象。

二、为什么要使用委托:记得博主刚开始做项目的时候看到委托的写法就头大,总觉得这是没事找事,唯一的好处貌似就是代码看上去很酷~~随着工作的累积,发现项目中某些小的需求使用这种轻量级的委托来实现的时候确实能减少很多代码量。

三、委托的使用:

1、.Net Framework 里面的委托类型:使用过委托的朋友可能注意到了C#里面定义了两种类型的委托变量,基本能满足我们的一般需求。

(1)Action类型的委托:C#里面定义Action委托用于抽象化那种没有返回值的方法。将Action变量转到定义可知它的最简单形式:

    // 摘要:
// 封装一个方法,该方法不具有参数并且不返回值。
[TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
public delegate void Action();

它定义是就是一种没有返回值没有参数的委托。同时Action还提供了16个泛型的委托,用于定义方法的传入参数:

我们来看他们的使用方法,我们首先定义测试的方法:

        private static void Test5(int a, int b, int c)
{
//......
} //无参数无返回值
private static void Test1()
{
Console.WriteLine("Func Test1, No Parameter");
} //有参数无返回值
private static void Test2(string str)
{
Console.WriteLine("Func Test2, Parameter is" + str);
} //无参数有返回值
private static object Test3()
{
Console.WriteLine("Func Test3, Parameter");
return Guid.NewGuid().ToString();
} //有参数有返回值
private static object Test4(string strRes)
{
Console.WriteLine("Func Test4, Parameter and Return Value");
return strRes;
}

调用:

        static void Main(string[] args)
{
//1.无参无返回值方法
var oAction1 = new Action(Test1);
oAction1.Invoke();//调用方式一
oAction1();//调用方式二 //2.有参无返回值
var oAction2 = new Action<int, int, int>(Test5);
oAction2.Invoke(, , );
oAction2(, , );
//匿名方法的调用
var oAction3 = new Action<int, int, int>((a,b,c) => {
//......
});
oAction3.Invoke(, , );
}

(2)Func类型的委托:还记得Linq里面的扩展方法Where()、Select()等方法的参数吗。public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)。这里的参数就是一个Func类型的委托。C#里面Func类型的委托用于处理有参数有返回值的方法。不多说,上代码:

     static void Main(string[] args)
{
var oFunc1 = new Func<object>(Test3);
var ofuncRes1 = oFunc1.Invoke();
var oFunc2 = new Func<string, object>(Test4);
oFunc2("a");
}

知道了Func的方法就可以推想到我们神奇的lamada表达式了,其实lamada表达式就是一个匿名的委托。

var lstTest = new List<string>();
var lstRes = lstTest.Where(x => x.Contains("_"));

这个Where里面的lamada表达式我们把他拆解:

private static bool TestWhere(string x)
{
return x.Contains("_");
}
var oFunc = new Func<string, bool>(TestWhere);
lstRes = lstTest.Where(oFunc);

是不是一样一样的~~

2、自定义委托:

public delegate void TestDelegate(string str);

其实很多人应该都自己写过Action、Func类型的委托。其实自己定义一个泛型委托也很简单:

public delegate void MyAction<in T>();
public delegate TResult MyFunc<in T, out TResult>(T arg);

其实使用起来和系统的Action和Func基本没有区别。

3、委托的合并和拆解就放在事件里面分享了。这篇且过之。。。

4、如果按照上面的方法去使用委托,那真的是要别扭死人了,因为调用方法直接用方法名调用就好了,何必还要定义一个委托变量去调用,这不是将简单问题复杂化么。确实,上面只是为了介绍委托而写的代码,实际项目中肯定不会这么用。其实委托在项目中一般用在将委托变量作为参数传递或者函数回调。来看下面代码:

   class Program
{
static void Main(string[] args)
{ Person strHelper = new Person();
string r1 = strHelper.ProcessFunc("中国人", "你好", new MyDelegate(strHelper.ChineseSayHello));
string r2 = strHelper.ProcessFunc("English", "Hello", new MyDelegate(strHelper.EnglishSayHello));
string r3 = strHelper.ProcessFunc("Japanese", "こんにちは", new MyDelegate(strHelper.JapaneseSayHello)); Console.WriteLine(r1);
Console.WriteLine(r2);
Console.WriteLine(r3); Console.ReadKey();
} } public delegate string MyDelegate(string s1, string s2);
public class Person
{
public string ProcessFunc(string s1, string s2, MyDelegate process)
{
return process(s1, s2);
} public string ChineseSayHello(string s1, string s2)
{
return s1 +","+ s2;
} public string EnglishSayHello(string s1, string s2)
{
return s1 + "," + s2;
} public string JapaneseSayHello(string s1, string s2)
{
return s1 +","+ s2;
}
}

得到结果:

public string ProcessFunc(string s1, string s2, MyDelegate process)里面定义了一个回调函数,可以将任意一个符合这个委托的方法传递进去,得到想对应的结果。细看这种设计是不是和工厂设计模式十分相似,我简单构造了个工厂:

public class Person
{
public virtual string SayHello(string s2)
{
return s2;
}
}
public class Chinese : Person
{
public override string SayHello(string s2)
{
return "中国人," + s2;
}
} public class English : Person
{
public override string SayHello(string s2)
{
return "English," + s2;
}
} public class Japanese : Person
{
public override string SayHello(string s2)
{
return "Japanese," + s2;
}
} //Main函数里面调用
class Program
{
static void Main(string[] args)
{
var r1 = GetPerson("你好").SayHello("你好");
var r2 = GetPerson("Hello").SayHello("Hello");
var r3 = GetPerson("こんにちは").SayHello("こんにちは");
Console.WriteLine(r1);
Console.WriteLine(r2);
Console.WriteLine(r3); Console.ReadKey();
} public static Person GetPerson(string strType)
{
if (strType == "你好")
return new Chinese();
else if (strType == "Hello")
return new English();
else
return new Japanese();
} }

得到结果和上面相同:

这样一比较是不是对委托的用法有点感觉了呢~~如果你不怕麻烦,可以在项目是用起来试试,相信你会有收获~~

示例下载

C#基础系列——委托实现简单设计模式的更多相关文章

  1. C#基础系列——委托和设计模式(二)

    前言:前篇 C#基础系列——委托实现简单设计模式 简单介绍了下委托的定义及简单用法.这篇打算从设计模式的角度去解析下委托的使用.我们知道使用委托可以实现对象行为(方法)的动态绑定,从而提高设计的灵活性 ...

  2. C#基础系列——异步编程初探:async和await

    前言:前面有篇从应用层面上面介绍了下多线程的几种用法,有博友就说到了async, await等新语法.确实,没有异步的多线程是单调的.乏味的,async和await是出现在C#5.0之后,它的出现给了 ...

  3. C#基础系列——一场风花雪月的邂逅:接口和抽象类

    前言:最近一个认识的朋友准备转行做编程,看他自己边看视频边学习,挺有干劲的.那天他问我接口和抽象类这两个东西,他说,既然它们如此相像, 我用抽象类就能解决的问题,又整个接口出来干嘛,这不是误导初学者吗 ...

  4. c#基础系列(转)

    转:http://www.cnblogs.com/landeanfen/p/4953025.html C#基础系列——一场风花雪月的邂逅:接口和抽象类 前言:最近一个认识的朋友准备转行做编程,看他自己 ...

  5. C#基础系列——再也不用担心面试官问我“事件”了

    前言:作为.Net攻城狮,你面试过程中是否遇到过这样的问题呢:什么是事件?事件和委托的区别?既然事件作为一种特殊的委托,那么它的优势如何体现?诸如此类...你是否也曾经被问到过?你又是否都答出来了呢? ...

  6. C#基础篇——委托

    前言 在本章中,主要是借机这个C#基础篇的系列整理过去的学习笔记.归纳总结并更加理解透彻. 在.Net开发中,我们经常会遇到并使用过委托,如果能灵活的掌握并加以使用会使你在编程中游刃有余,然后对于很多 ...

  7. [.net 面向对象编程基础] (21) 委托

    [.net 面向对象编程基础] (20)  委托 上节在讲到LINQ的匿名方法中说到了委托,不过比较简单,没了解清楚没关系,这节中会详细说明委托. 1. 什么是委托? 学习委托,我想说,学会了就感觉简 ...

  8. C#基础系列:实现自己的ORM(反射以及Attribute在ORM中的应用)

    反射以及Attribute在ORM中的应用 一. 反射什么是反射?简单点吧,反射就是在运行时动态获取对象信息的方法,比如运行时知道对象有哪些属性,方法,委托等等等等.反射有什么用呢?反射不但让你在运行 ...

  9. 你所不知道的ASP.NET Core MVC/WebApi基础系列(一)

    前言 最近发表的EF Core貌似有点多,可别误以为我只专攻EF Core哦,私下有时间也是一直在看ASP.NET Core的内容,所以后续会穿插讲EF Core和ASP.NET Core,别认为你会 ...

随机推荐

  1. 关于C#消息调度(作业日志)

    在Windows定时作业中,其实有多种关于作业调度形式,比如Windows Services 和 Windows Form 都可以做到,各有各的好处.现在来介绍下使用插件的形式进行定时作业. 1.用q ...

  2. Introduction to Microsoft Dynamics 365 licensing

    Microsoft Dynamics 365 will be released on November 1. In preparation for that, Scott Guthrie hosted ...

  3. Azure IoT带来更高效的新能源生产和会看人脸色的无人超市

    全球分析机构都认为物联网将在未来几年呈现爆发式增长,到2020年,各种传感器.新型物联网设备,再加上传统PC.智能手机.平板电脑.网络电视,以及各类可穿戴智能设备,将交织成一个由300亿到500亿台设 ...

  4. Android中的AlertDialog使用示例三(单向选择确定对话框)

    在Android开发中,我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框,AlertDialog实现方法为建造者模式. ...

  5. Android编码规范03

    一.整个项目的目录规范化sundy老师建议有:系统目录规范.源代码目录规范. 1.系统目录规范: 指项目目录中不仅包括源代码,还需要包括:需求相关文档.设计文档.计划日志文档.测试文档.项目进行中学习 ...

  6. 开启我的Android之旅-----记录Android环境搭建遇到的问题

    在现在这个离不开手机的时代,对于手机APP的开发也是一个很大的市场,所以自己也想去探一探手机APP开发,在我们进行Android开发的第一步就是搭建环境,具体怎么搭建我就不说,这里记录一下在搭建环境的 ...

  7. iOS 陀螺仪,加速度计

    atan2(x, y)反正切函数  x是对边  y临边 data.acceleration  加速度值,当手机水平放置时值为(0,0,-1),当手机竖直放置时值为(0,-1,0),判断手机拿起状态可以 ...

  8. 史上最全的ASP.NET MVC路由配置

    MVC将一个Web应用分解为:Model.View和Controller.ASP.NET MVC框架提供了一个可以代替ASP.NETWebForm的基于MVC设计模式的应用. AD:51CTO 网+ ...

  9. yii2缓存的介绍和使用

    作者:白狼 出处:http://www.manks.top/yii2_cache.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律 ...

  10. Guest Speaker on 2015 WinHEC Shenzhen 秋季大会

    继今年3月份的WinHEC春季大会,秋季大会于11月10日-11日深圳如期举行.此次大会的主题是Windows 10 IoT和Microsoft Azure,云和端的无缝连接是微软物联网解决方案的典型 ...