前言:上一篇介绍了下多线程的相关知识: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. js 模块化的一些理解和es6模块化学习

    模块化 1 IIFE 2 commonjs 3 浏览器中js的模块化 4 简单理解模块加载器的原理  5 es6 之前在参加百度前端技术学院做的小题目的时候,自己写模块的时候 都是写成立即调用表达式( ...

  2. 轻松掌握:JavaScript观察者模式

    观察者模式 观察者模式也叫"订阅者/发布者"模式,定义对象间的一种一对多的依赖关系,发布者可以向所有订阅者发布消息. 观察者模式被广泛地应用于JavaScript客户端编程中.所有 ...

  3. include的用法例子,以及include+merge的用法例子

    [include+LinearLayout]的使用例子 AndroidIncludeLayout.java package com.AndroidIncludeLayout; import andro ...

  4. GCD

    Grand Central Dispatch(GCD)包含语言特点.运行库和系统增强功能,它提供系统的.综合的改进,进而去支持并发代码在iOS和OSX多核硬件上的执行. 子系统.CoreFoundat ...

  5. HTML5-02 元素

    概述 HTML 文档主要由元素组成,且主要分为两大部分:头部 和 主体.如图: 头部 概述 <head> 元素包含了所有的头部标签.<head> 元素中通常包含脚本(scrip ...

  6. 学习Maven之Cobertura Maven Plugin

    cobertura-maven-plugin是个什么鬼? cobertura-maven-plugin是一个校验单元测试用例覆盖率的工具,可以生成一个测试覆盖率报告,可以给单元测试用例编写提供参考. ...

  7. 你买了多少ERP?

    企业使用ERP(或是其他管理系统),有三种模式:自开发.采购.租赁(SAAS).不知道企业的各级管理者们,是否想过这个问题——我们到底买(做.租)了多少“量”的ERP呢? 这个问题也许不是那么好回答. ...

  8. Xamarin For Visual Studio 3.0.54.0 完整离线破解版(C# 开发Android、IOS工具 吾乐吧软件站分享)

    Xamarin For Visual Studio就是原本的Xamarin For Android 以及 Xamarin For iOS,最新版的已经把两个独立的插件合并为一个exe安装包了.为了区分 ...

  9. MS SQL 监控错误日志的告警信息

    SQL Server的错误消息(Error Message)按照消息的严重级别一共划分25个等级,级别越高,表示严重性也越高.但是如果你统计sys.messages,你会发现,实际上只有16(SQL ...

  10. JSP分页显示实例(基于Bootstrap)

    首先介绍一款简单利落的分页显示利器:bootstrap-paginator 效果截图: GitHub官方下载地址:https://github.com/lyonlai/bootstrap-pagina ...