先看看委托的概述:

•委托类似于 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. Centos下LAMP环境搭建

    CentOs下环境搭建.2015.04.15.0001 Author:周凯 Time: 2015.04.15 版本号:2015.04.15.0001 安装过程 安装apache yum install ...

  2. jQuery无缝循环开源多元素动画轮播jquery.slides插件

    详细内容请点击 初始化插件: 一款基于jQuery无缝轮播图插件,支持图内元素动画,可以自定义动画类型$(".slideInner").slide({slideContainer: ...

  3. 使用T4为数据库自动生成实体类

    T4 (Text Template Transformation Toolkit) 是一个基于模板的代码生成器.使用T4你可以通过写一些ASP.NET-like模板,来生成C#, T-SQL, XML ...

  4. 很全的corel图像分类,场景识别图像库

    这是真正的Corel-5K图像集,共包含科雷尔(Corel)公司收集整理的5000幅图片,故名:Corel-5K,童鞋们可用于科学图像实验:分类.检索等.Corel-5k数据集是图像实验的事实标准数据 ...

  5. CCNA长语

    思科认证网络支持工程师(Cisco Certified Network Associate_CCNA) 专业英文词汇大全 10BaseT-----原始IEEE802.3标准的一部分,1OBaseT是1 ...

  6. SQL中各数据类型的长度、精度

    在 Microsoft? SQL Server? 中,每个列.局部变量.表达式和参数都有一个相关的数据类型,这是指定对象可持有的数据类型(整型.字符.money 等等)的特性. SQL Server ...

  7. 使用VS2015(c#)进行单元测试,显示测试结果与查看代码覆盖率

    创建测试的过程可参考如下链接 http://www.cnblogs.com/libaoquan/p/5296384.html (一)如何使用VS2015查看测试结果 问题描述:使用VS2010执行单元 ...

  8. UI3_视图切换

    // // ViewController.m // UI3_视图切换 // // Created by zhangxueming on 15/7/3. // Copyright (c) 2015年 z ...

  9. 什么是GPX

    GPX(GPS eXchange Format, GPS交换格式)是一个XML格式,为应用软件设计的通用GPS数据格式. 它可以用来描述路点.轨迹.路程.这个格式是免费的,可以在不需要付任何许可费用的 ...

  10. 使用单用户模式破解Linux密码

    使用单用户模式破解Linux密码 特别说明:在实际工作应用中,安装Linux操作系统必须设置装载口令,否则很容易被破解. 1.使用reboot指令重启Linux操作系统 2.在进入操作系统数秒时,单击 ...