先看看委托的概述:

•委托类似于 C++ 函数指针,但它们是类型安全的。

• 委托允许将方法作为参数进行传递。

• 委托可用于定义回调方法。

• 委托可以链接在一起;例如,可以对一个事件调用多个方法。

•方法不必与委托签名完全匹配。 有关更多信息,请参见 在委托中使用变体(C# 和 Visual Basic)。

• C# 2.0 版引入了匿名方法的 概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。 C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。 匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。 这些功能统称为匿名函数。 有关 lambda 表达式的更多信息,请参见 匿名函数(C# 编程指南)。

委托是一种定义方法签名的类型。 当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。 您可以通过委托实例调用方法。

委托用于将方法作为参数传递给其他方法。 事件处理程序就是通过委托调用的方法。 您可以创建一个自定义方法,当发生特定事件时某个类(例如 Windows 控件)就可以调用您的方法。

例子1:

    class Program
{ static void Main(string[] args)
{
Hello();
} static void Hello()
{
System.Console.WriteLine("Hello, Delegate!");
}
}

这是一个常见的方法, 输出一段字符串Hello, Delegate!

下面我们来把他写成委托,

    class Program
{
delegate void PrintHello(); static void Main(string[] args)
{
PrintHello ph = new PrintHello(Hello);
ph.Invoke();
} static void Hello()
{
System.Console.WriteLine("Hello, Delegate!");
}
}

这里的PrintHello的方法类型需要和Hello保持一直,另外参数也需要保持一致,现在是无参数的.讲Hello作为参数传到委托中,然后用Invoke调用.
以上代码也会输出,Hello, Delegate!因为invoke了这个方法.

从.net 2.0开始就使用匿名委托, 可以这样申明

delegate { };

或者带参数的

delegate (string i){ };

{}括号中可以写需要执行的逻辑代码.

有了匿名委托我们就可以偷一下懒了,可以把上面的例子改成如下:

    class Program
{
delegate void PrintHello(); static void Main(string[] args)
{
PrintHello ph = delegate
{
System.Console.WriteLine("Hello, Delegate!");
};
ph.Invoke(); } //static void Hello()
//{
// System.Console.WriteLine("Hello, Delegate!");
//}
}

在.net 3.0中新加了Action<T> 无返回的委托, Predicate<T>有返回值,且返回true或false的委托.

我们可以将上面的例子改成有参数的,

    class Program
{
static Action<string> print = delegate(string i) { System.Console.WriteLine("Hello, {0}!",i); }; static void Main(string[] args)
{
print.Invoke("Delegate");
}
}

或者用lambda表达式替代匿名委托,进一步偷懒..

    class Program
{
static Action<string> print = (i)=>{ System.Console.WriteLine("Hello, {0}!",i); }; static void Main(string[] args)
{
print.Invoke("Delegate");
}
}

以上会输出Hello,Delegate!因为将Delegate传入到最后输出.

再来讲解一下Predicate这个只返回true or false的委托,如下:

    class Program
{
static Predicate<string> print = (i) => { return string.IsNullOrEmpty(i); }; static void Main(string[] args)
{
System.Console.WriteLine(print.Invoke("Hello, Delegate!"));
}
}

以上代码会输入true因为i不是为null or empty.

在.net 3.5中又新加了Action(无返回值的委托,类似于delegate void)和Func<T,T> 带返回参数的,参数类型是T,返回类型也可以是int,string等..

所以刚才的无参数的例子又可以写成这样:

    class Program
{
static Action print = () => { System.Console.WriteLine("Hello, Delegate!"); }; static void Main(string[] args)
{
print.Invoke();
}
}

再来看看Func<T,TReslut> 第一个T代表参数的类型,第一个TReslut代表返回结果的类型。

如下,参数的类型是int,返回的类型是string.

    class Program
{
static Func<int,string> print = (i) => { return "Hello, Delegate!"+i.ToString(); }; static void Main(string[] args)
{
System.Console.WriteLine(print.Invoke());
}
}

输出的结果是:Hello, Delegate!0

再来看看委托的回调函数,如下:

    class Program
{
delegate string callback(string firstName, string lastName); static void Main(string[] argss)
{
DoCallback("Charlie", "Wang", en_US);
DoCallback("Tom", "Chen", ch_ZN); } static void DoCallback(string firstName, string lastName, callback call)
{
string result=call(firstName, lastName);
Console.WriteLine(result);
} static string en_US(string firstName, string lastName)
{
return firstName + " ," + lastName;
} static string ch_ZN(string firstName, string lastName)
{
return lastName+", "+firstName;
}
}

输出的结果为:

Charlie ,Wang
Chen, Tom

我们还可以将以上代码进一步精简,用Func代替.

    class Program
{
static void Main(string[] argss)
{
DoCallback("Charlie", "Wang", en_US);
DoCallback("Tom", "Chen", ch_ZN); } static void DoCallback(string firstName, string lastName, Func<string,string,string> callback)
{
string result = callback(firstName, lastName);
Console.WriteLine(result);
} static string en_US(string firstName, string lastName)
{
return firstName + " ," + lastName;
} static string ch_ZN(string firstName, string lastName)
{
return lastName+", "+firstName;
}
}

我们还可以这样写.

    class Program
{
static void Main(string[] argss)
{
DoCallback("Charlie", "Wang", en_US);
DoCallback("Tom", "Chen", ch_ZN);
DoCallback("Kevin", "Liu", (lastName, firstName) => { return string.Format("This is {0} {1}", lastName, firstName);});
} static void DoCallback(string firstName, string lastName, Func<string,string,string> callback)
{
string result = callback(firstName, lastName);
Console.WriteLine(result);
} static string en_US(string firstName, string lastName)
{
return firstName + " ," + lastName;
} static string ch_ZN(string firstName, string lastName)
{
return lastName+", "+firstName;
}
}

输出结果为:

Charlie ,Wang
Chen, Tom
This is Kevin Liu

委托在很多时候使用可以精简我们的代码,看起来比较直观,下面是个很经典的案例:

    class Program
{
static void Main(string[] args)
{
B b = new B();
}
}
class A
{
public A()
{
Print();
}
public virtual void Print() { }
} class B : A
{
int x = ;
int y; public B()
{
y = -;
}
public override void Print()
{
System.Console.WriteLine("x={0},y={1}", x, y);
}
}

各位读者看看以上代码输出什么?

    class Program
{
static void Main(string[] args)
{
B b = new B();
b.print();
}
}
class A
{
public A()
{
Print();
}
public virtual void Print() { }
} class B : A
{
int x = ;
int y;
public Action print = delegate { }; public B()
{
y = -;
this.print = Print;
}
public override void Print()
{
System.Console.WriteLine("x={0},y={1}", x, y);
}
}

然后再看看以上代码又输出什么?

C# 浅谈委托----温故而知新的更多相关文章

  1. 【C#系列】浅谈委托和委托

    本篇文章更适合具有一定开发经验,一定功底,且对底层代码有所研究的朋友!!! 本篇文章主要采用理论和代码实例相结合方法来论述委托和事件,涉及到一些边界技术,如软件架构的OCP原则(开-闭原则), 软件架 ...

  2. NET中级课--浅谈委托,事件,异步调用,回调等概念

    直接说题. 委托         首先明确它是什么,其实就是一个类,定义一个委托即定义一个类,那么它是什么类?用来说明方法的类型的类.字段有类型,那么方法其实也有类型,就是委托.       委托是某 ...

  3. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  4. 浅谈线程池(中):独立线程池的作用及IO线程池

    原文地址:http://blog.zhaojie.me/2009/07/thread-pool-2-dedicate-pool-and-io-pool.html 在上一篇文章中,我们简单讨论了线程池的 ...

  5. 浅谈线程池(上):线程池的作用及CLR线程池

    原文地址:http://blog.zhaojie.me/2009/07/thread-pool-1-the-goal-and-the-clr-thread-pool.html 线程池是一个重要的概念. ...

  6. 谁还没遇上过NoClassDefFoundError咋地——浅谈字节码生成与热部署

    谁还没遇上过NoClassDefFoundError咋地--浅谈字节码生成与热部署 前言 在Java程序员的世界里,NoClassDefFoundError是一类相当令人厌恶的错误,因为这类错误通常非 ...

  7. 【Unity游戏开发】浅谈Lua和C#中的闭包

    一.前言 目前在Unity游戏开发中,比较流行的两种语言就是Lua和C#.通常的做法是:C#做些核心的功能和接口供Lua调用,Lua主要做些UI模块和一些业务逻辑.这样既能在保持一定的游戏运行效率的同 ...

  8. 浅谈.Net异步编程的前世今生----APM篇

    前言 在.Net程序开发过程中,我们经常会遇到如下场景: 编写WinForm程序客户端,需要查询数据库获取数据,于是我们根据需求写好了代码后,点击查询,发现界面卡死,无法响应.经过调试,发现查询数据库 ...

  9. 浅谈Kotlin(三):类

    浅谈Kotlin(一):简介及Android Studio中配置 浅谈Kotlin(二):基本类型.基本语法.代码风格 浅谈Kotlin(三):类 浅谈Kotlin(四):控制流 前言: 已经学习了前 ...

随机推荐

  1. Backbone.js学习之初识hello-world

    说了好久好久要学习Backbone.js,现在终于下定决心开始学习了.然后呢,就根据我的学习进度在这里做个简单的记录,方便新人,也方便我自己以后回忆. 准备 用bower下载这几个库或框架也是醉了.. ...

  2. java识别验证码

    所需资源下载链接(资源免费,重在分享) Tesseract:http://download.csdn.net/detail/chenyangqi/9190667 jai_imageio-1.1-alp ...

  3. Javascript之数据执行原理探究

    Javascript在Web服务器端执行原理: 1.客户端请求数据,即我们在上网时在地址栏中输入某个网址,浏览器接收到数据之后,向远程web服务器发送请求报文. 2.web服务器响应请求,web服务器 ...

  4. Sql server For XML Path 学习

    最近看到太多人问这种问题   自己也不太了解  就在网上学习学习 自己测试一番 CREATE TABLE test0621 (id INT,NAME NVARCHAR(max)) INSERT tes ...

  5. 关于DB2 SQL0805N找不到程序包的错误解决办法

    DB2在执行SQL语句的时候会使用内部定义的包(package)来保持不同级别的游标的稳定性, 包的名字就是“ULLID.SYSLH2XX“. DB2 里面默认的时候会创建3个这样的包即SYSLH20 ...

  6. 【学习笔记】【C语言】流程控制

    顺序结构:默认的流程结构.按照书写顺序执行每一条语句. 选择结构:对给定的条件进行判断,再根据判断结果来决定执行哪一段代码. 循环结构:在给定条件成立的情况下,反复执行某一段代码.

  7. Tables for condition techniques

    T682i  -- Access sequence and the tables   T685  -- Condition types and Access sequences   T683s  -- ...

  8. Linux下编译安装mysql-5.0.45.tar.gz

    安装环境:VMware9(桥接模式) + Linux bogon 2.6.32-642.3.1.el6.x86_64(查看linux版本信息:uname -a) 先给出MySQL For Linux ...

  9. fpm打包redis3.0.7

    1.安装redis tar -xf redis-3.0.7.tar.gz -C /usr/local cd /usr/local && mv redis-3.0.7 redis cd ...

  10. Linux下的vi编辑器与gcc工具的使用

    最近在网上找了些视频,自学了一点Linux环境下,C编程的方法. 注 vi与vim是有区别的,vim打开的源码文件其中的关键字是有颜色的. vi编辑器有3种模式,命令行模式,插入模式,底行模式. 如果 ...