委托:

还记得C++里的函数指针么?大家可以点击这里查看一下以前的笔记。C#的委托和C++中的函数指针效果一致。

当我们需要将函数作为对象进行传递和使用时就需要用到委托。

下面我们看一个例子:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
class Program
{
static void Main(string[] args)
{
//声明委托的实例
ProcessDelegate pd; //指定委托的函数
pd = Multiply;
Console.WriteLine(pd(, )); //指定委托的函数
pd = Divide;
Console.WriteLine(pd(, )); //将委托作为参数传递
Func1(pd);
//将函数直接作为参数传递
Func1(Multiply); Console.ReadKey();
} /// <summary>
/// 声明一个委托.
/// </summary>
delegate double ProcessDelegate(double param1, double param2); static double Multiply(double param1, double param2)
{
return param1 * param2;
} static double Divide(double param1, double param2)
{
return param1 / param2;
} /// <summary>
/// 参数为委托类型的函数.
/// </summary>
static void Func1(ProcessDelegate pd)
{
Console.WriteLine(pd(, ));
}
}
}

运行的结果如下:


初始化定义和委托推断:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
class Program
{
delegate string GetAString(); static void Main(string[] args)
{
int x = ;
//这里我称为初始化定义, 注意不能写成 x.ToString()
GetAString method = new GetAString(x.ToString);
Console.WriteLine(method()); x = ;
//通过委托推断可以简化代码编写, 注意不能写成 x.ToString()
GetAString method2 = x.ToString;
Console.WriteLine(method2()); Console.ReadKey();
}
}
}

多播委托:

多播委托支持“+”“-”操作符,可以添加多个方法到同一个委托中,当委托被执行时,并不会按照添加的顺序依次调用函数,调用顺序是无法保证的。

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
class Program
{
delegate void DoubleOp(double value); public static void Func1(double value)
{
double result = value * ;
Console.WriteLine("Func1 value: {0}, result: {1}", value, result);
} public static void Func2(double value)
{
double result = value * value;
Console.WriteLine("Func2 value: {0}, result: {1}", value, result);
} static void Main(string[] args)
{
DoubleOp op = Func1;
//添加一个方法
op += Func2; op();
Console.WriteLine();
op();
Console.WriteLine(); //去掉一个方法
op -= Func1; op(); Console.ReadKey();
}
}
}

下面是运行的结果:

 Func1 value: , result:
Func2 value: , result: Func1 value: , result:
Func2 value: , result: Func2 value: , result:

匿名函数:

使用时直接进行定义的函数。

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
class Program
{
delegate string GetString(float num); static void Main(string[] args)
{
//定义匿名函数
GetString m = delegate(float num)
{
return num.ToString();
};
Func(m, 10.5f); //直接传递匿名函数
Func(delegate(float num)
{
num *= 2.0f;
return num.ToString();
}, 20.5f); Console.ReadKey();
} static void Func(GetString method, float num)
{
Console.WriteLine("Func: " + method(num));
}
}
}

下面是运行的结果:

 Func: 10.5
Func:

Lambda表达式:

Lambda表达式可以用来简化匿名函数的写法,如果把上面的示例改为Lambda表达试则如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
class Program
{
delegate string GetString(float num); static void Main(string[] args)
{
//使用表达式进行简写
GetString m = num =>
{
return num.ToString();
};
Func(m, 10.5f); //直接传递表达试
Func(num =>
{
num *= 2.0f;
return num.ToString();
}, 20.5f); Console.ReadKey();
} static void Func(GetString method, float num)
{
Console.WriteLine("Func: " + method(num));
}
}
}

Lambda表达式可以去掉函数参数的类型,因为该类型编译器可以从上下文中获得。如果存在多个参数则需要添加括号,如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
class Program
{
delegate string GetString(float num, int num2); static void Main(string[] args)
{
//使用表达式进行简写
GetString m = (num, num2) =>
{
return num.ToString() + "," + num2.ToString();
};
Func(m, 10.5f, ); //直接传递表达试
Func((num, num2) =>
{
num *= 2.0f;
num += num2;
return num.ToString();
}, 20.5f, ); Console.ReadKey();
} static void Func(GetString method, float num, int num2)
{
Console.WriteLine("Func: " + method(num, num2));
}
}
}

下面是运行的结果:

 Func: 10.5,
Func:

如果代码仅有一行还可以省略return和大括号,如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
class Program
{
delegate string GetString(float num, int num2); static void Main(string[] args)
{
//使用表达式进行简写
GetString m = (num, num2) => num.ToString() + "," + num2.ToString();
Func(m, 10.5f, ); //直接传递表达式
Func((num, num2) => num.ToString() + "," + num2.ToString(), 20.5f, ); Console.ReadKey();
} static void Func(GetString method, float num, int num2)
{
Console.WriteLine("Func: " + method(num, num2));
}
}
}

下面是运行的结果:

 Func: 10.5,
Func: 20.5,

这里引入了一个新的知识点协变和抗变,大家可以自行搜索,或者查看协变和抗变的文章点击这里

事件:

C#里的事件使用event关键字定义,无需实例化就可以使用,可以将其看做一个特殊的委托对象,下面我们看看一个例子。

EventDispatcher.cs(用来定义和发送特定事件的类):

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
/// <summary>
/// 事件发送类.
/// </summary>
class EventDispatcher
{
/// <summary>
/// 定义特定的事件委托, 注意不要有返回值.
/// </summary>
/// <param name="sender">发送者.</param>
/// <param name="args">附带的参数.</param>
public delegate void MyEventHandler(object sender, MyEventArgs args); /// <summary>
/// 事件对象, 所有的回调都可以添加到该对象上, 不需要实例化就能使用.
/// </summary>
public event MyEventHandler onCustom; /// <summary>
/// 构造函数.
/// </summary>
public EventDispatcher()
{
} /// <summary>
/// 发送一个自定义事件.
/// </summary>
/// <param name="data">数据.</param>
public void dispatchCustom(String data)
{
onCustom(this, new MyEventArgs(data));
}
} /// <summary>
/// 自定义事件参数类.
/// </summary>
class MyEventArgs : EventArgs
{
public String data; public MyEventArgs(String data)
{
this.data = data;
}
}
}

Program.cs(主程序,测试类):

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
class Program
{
static void Main(string[] args)
{
new Program(); Console.ReadKey();
} public Program()
{
EventDispatcher ed = new EventDispatcher(); //第一种方式
EventDispatcher.MyEventHandler meh = new EventDispatcher.MyEventHandler(CustomHandler);
ed.onCustom += meh;
ed.dispatchCustom("Hello One!");
ed.onCustom -= meh; //第二种方式
ed.onCustom += new EventDispatcher.MyEventHandler(CustomHandler);
ed.dispatchCustom("Hello Two!");
//下面两种方式都可以删除注册的事件处理函数
ed.onCustom -= new EventDispatcher.MyEventHandler(CustomHandler);
//ed.onCustom -= CustomHandler; //简写方式
ed.onCustom += CustomHandler;
ed.dispatchCustom("Hello Three!");
ed.onCustom -= CustomHandler; //匿名函数写法
ed.onCustom += delegate(object sender, MyEventArgs args)
{
Console.WriteLine("Event Handler (delegate) : " + args.data);
};
ed.dispatchCustom("Hello Four!"); //Lambda 写法
ed.onCustom += (sender, args) =>
{
Console.WriteLine("Event Handler (lambda) : " + args.data);
};
ed.dispatchCustom("Hello Five!"); //简写 Lambda
ed.onCustom += (sender, args) => Console.WriteLine("Event Handler (lambda) : " + args.data);
ed.dispatchCustom("Hello six!");
} private void CustomHandler(object sender, MyEventArgs args)
{
Console.WriteLine("Event Handler : " + args.data);
}
}
}

下面是程序运行的结果:

 Event Handler : Hello One!
Event Handler : Hello Two!
Event Handler : Hello Three!
Event Handler (delegate) : Hello Four!
Event Handler (delegate) : Hello Five!
Event Handler (lambda) : Hello Five!
Event Handler (delegate) : Hello six!
Event Handler (lambda) : Hello six!
Event Handler (lambda) : Hello six!

委托、匿名函数、Lambda表达式和事件的学习的更多相关文章

  1. (28)C#委托,匿名函数,lambda表达式,事件

    一.委托 委托是一种用于封装命名和匿名方法的引用类型. 把方法当参数,传给另一个方法(这么说好理解,但实际上方法不能当参数,传入的是委托类型),委托是一种引用类型,委托里包含很多方法的引用 创建的方法 ...

  2. 【Unity|C#】基础篇(9)——匿名函数 / Lambda表达式

    [学习资料] <C#图解教程>(第13章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu. ...

  3. 函数:lambda表达式 - 零基础入门学习Python021

    函数:lambda表达式 让编程改变世界 Change the world by program lambda表达式 Python允许使用lambda关键字来创建匿名函数.我们提到一个新的关键字:匿名 ...

  4. 委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件【转】

    1. 委托 From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html 类是对象的抽象,而委托则可以看成是函数的抽象.一个委 ...

  5. 匿名函数 lambda表达式(lambda expression)

    阅读g2log时,发现有两行代码居然看不懂. 1. auto bg_call =  [this, log_directory]() {return pimpl_->backgroundChang ...

  6. C#多线程+委托+匿名方法+Lambda表达式

    线程 下面是百度写的: 定义英文:Thread每个正在系统上运行的程序都是一个进程.每个进程包含一到多个线程.进程也可能是整个程序或者是部分程序的动态执行.线程是一组指令的集合,或者是程序的特殊段,它 ...

  7. Qt中使用匿名函数lambda表达式

    一.为什么要使用匿名函数lamdba 首先,lambda表达式可以使代码变得简单,C++中,一个lambda表达式表示一个可调用的代码单元.如代码: #include <QCoreApplica ...

  8. Python匿名函数——lambda表达式

    如果要定义的函数很简单,一个return语句就能搞定,可以使用lambda表达式来定义, lambda表达式的语法如下: lambda parameters: expression lambda表达式 ...

  9. python做中学(八)匿名函数lambda的用法

    匿名函数,顾名思义即没有名称的函数,和def定义的函数的最大区别在于匿名函数创建后返回函数本身(即匿名函数不需要return来返回值),表达式本身结果就是返回值,而def创建后则赋值给一个变量名,在P ...

随机推荐

  1. ArrayList源代码深入剖析

    第1部分 ArrayList介绍ArrayList底层采用数组实现,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAccess, Cloneable, java. ...

  2. fedora之防火墙

    通过iptables的设置可以学一些东西 从配置菜单关闭防火墙是不起作用的,索性在安装的时候就不要装防火墙查看防火墙状态:/etc/init.d/iptables status暂时关闭防火墙:/etc ...

  3. 通过 PHP 判断用户的设备是否是移动设备

    <?php function isMobile() { // 如果有HTTP_X_WAP_PROFILE则一定是移动设备 if (isset ($_SERVER['HTTP_X_WAP_PROF ...

  4. 页面滚动动态加载数据,页面下拉自动加载内容 jquery

    <!DOCTYPE=html> <html> <head> < script src="js/jquery.js" type=" ...

  5. 获取View的高度宽度,屏幕参数,状态栏高度

    基础 各区域示例,注意绿色,紫色,橙色区域 注意: 在onCreate只是对象的初始创建过程,这时并没有draw,这时view.getHeight返回0,可在onStart里用getHeight等. ...

  6. Grunt 初体验

    对于没有接触过类似自动化工具的朋友,对 grunt 也许只是停留在听过阶段,而并没有真正的使用过.今天就从最初级的教程说起.在开始教程之前,需要先确保你已经安装了 node. 下面就开始来讲解 gru ...

  7. 1067. Disk Tree(字符串)

    1067 破题啊  写完发现理解错题意了 子目录下会有跟之前重名的 把输入的字符串存下来 排下序 然后依次找跟上面有没有重的 #include <iostream> #include< ...

  8. poj2392

    首先按限制高度排序,然后按多重背包做dp 这里的背包只用知道每种状态是否可行,所以 这里的多重背包可以变成O(nm) ; ..,..,..] of longint;     a,b:..] of lo ...

  9. 各种好用的工具之一 ---- PNGGauntlet

    1.PNGGauntlet实际上是一个图形前端,压缩图像的过程中使用的是PNGOUT, OptiPNG, 和DeflOpt这三款软件. 软件官网:http://pnggauntlet.com/ 可自行 ...

  10. HHVM 是如何提升 PHP 性能的?

    背景 HHVM 是 Facebook 开发的高性能 PHP 虚拟机,宣称比官方的快9倍,我很好奇,于是抽空简单了解了一下,并整理出这篇文章,希望能回答清楚两方面的问题: HHVM 到底靠谱么?是否可以 ...