委托、匿名函数、Lambda表达式和事件的学习
委托:
还记得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表达式和事件的学习的更多相关文章
- (28)C#委托,匿名函数,lambda表达式,事件
一.委托 委托是一种用于封装命名和匿名方法的引用类型. 把方法当参数,传给另一个方法(这么说好理解,但实际上方法不能当参数,传入的是委托类型),委托是一种引用类型,委托里包含很多方法的引用 创建的方法 ...
- 【Unity|C#】基础篇(9)——匿名函数 / Lambda表达式
[学习资料] <C#图解教程>(第13章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu. ...
- 函数:lambda表达式 - 零基础入门学习Python021
函数:lambda表达式 让编程改变世界 Change the world by program lambda表达式 Python允许使用lambda关键字来创建匿名函数.我们提到一个新的关键字:匿名 ...
- 委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件【转】
1. 委托 From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html 类是对象的抽象,而委托则可以看成是函数的抽象.一个委 ...
- 匿名函数 lambda表达式(lambda expression)
阅读g2log时,发现有两行代码居然看不懂. 1. auto bg_call = [this, log_directory]() {return pimpl_->backgroundChang ...
- C#多线程+委托+匿名方法+Lambda表达式
线程 下面是百度写的: 定义英文:Thread每个正在系统上运行的程序都是一个进程.每个进程包含一到多个线程.进程也可能是整个程序或者是部分程序的动态执行.线程是一组指令的集合,或者是程序的特殊段,它 ...
- Qt中使用匿名函数lambda表达式
一.为什么要使用匿名函数lamdba 首先,lambda表达式可以使代码变得简单,C++中,一个lambda表达式表示一个可调用的代码单元.如代码: #include <QCoreApplica ...
- Python匿名函数——lambda表达式
如果要定义的函数很简单,一个return语句就能搞定,可以使用lambda表达式来定义, lambda表达式的语法如下: lambda parameters: expression lambda表达式 ...
- python做中学(八)匿名函数lambda的用法
匿名函数,顾名思义即没有名称的函数,和def定义的函数的最大区别在于匿名函数创建后返回函数本身(即匿名函数不需要return来返回值),表达式本身结果就是返回值,而def创建后则赋值给一个变量名,在P ...
随机推荐
- UIWebView与JS的深度交互
我要实现这样一个需求:按照本地的CSS文件展示一串网络获取的带HTML格式的只有body部分的文本,需要自己拼写完整的 HTML.除此之外,还需要禁用获取的HTML文本中自带的 < img &g ...
- Sequel Pro 免费的MySQL管理客戶端(有SSH部分)
官方站點:http://www.sequelpro.com Sequel Pro 的原名是 CocoaMySQL,是一个与 phpMyAdmin 類似的 MySQL 管理工具.它是由 Cocoa 和面 ...
- 安装Hadoop系列 — 导入Hadoop源码项目
将Hadoop源码导入Eclipse有个最大好处就是通过 "ctrl + shift + r" 可以快速打开Hadoop源码文件. 第一步:在Eclipse新建一个Java项目,h ...
- 【iOS开发】iOS7 兼容及部分细节
1:statusBar字体为白色 在plist里面设置View controller-based status bar appearance 为 NO:设置statusBarStyle 为 UISta ...
- jqueryrotate 使用 帮助 笔记 学习
1.想变角度 $("imgID").rotate(45); 2.想变角度时,有运动过程 $("imgID").rotate({animateTo:45} ...
- uva 489 Hangman Judge(水题)
题目:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&am ...
- Can't obtain the input stream from /docProps/app.xml
今天在做poi修改样式时,报了以下错误: Exception in thread "main" org.apache.poi.POIXMLException: java.io.IO ...
- 深入分析Cookie的安全性问题
Cookie的目的是为用户带来方便,为网站带来增值,一般情况下不会造成严重的安全威胁.Cookie文件不能作为代码执行,也不会传送病毒,它为用户所专有并只能由创建它的服务器来读取.另外,浏览器一般只允 ...
- 【转】 COCOS2D-X之使用CURL下载图片的一个简单Demo
#include"curl/curl.h" #pragma comment(lib,"libcurl_imp.lib") bool HelloWorld::i ...
- (转载)【C++】new A和new A()的区别详解
(转载)http://blog.csdn.net/xiajun07061225/article/details/8796257 我们在C++程序中经常看到两种new的使用方式:new A以及new A ...