前言

本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html 。本文主要学习记录以下内容:

  建议38、小心闭包中的陷阱

  建议39、了解委托的实质

  建议40、使用event关键字对委托施加保护

  建议41、实现标准的事件模型

建议38、小心闭包中的陷阱

  首先我们先来看一段代码:

    class Program
{
static void Main(string[] args)
{
List<Action> list = new List<Action>();
for (int i = ; i < ; i++)
{
Action t = () =>Console.WriteLine(i.ToString());
list.Add(t);
}
foreach (Action t in list)
{
t();
}
Console.ReadLine();
}
}

你设想的结果或许是0,1,2,3,4

但没想到执行后结果如下

通过IL可以查看代码,组合后大致代码如下:

    public class TempClass
{
public int i;
public void TempFunc()
{
Console.WriteLine(i.ToString());
} }
class Program
{
static void Main(string[] args)
{
List<Action> list = new List<Action>();
TempClass tempClass = new TempClass();
for (tempClass.i = ; tempClass.i < ; tempClass.i++)
{
Action t = tempClass.TempFunc;
list.Add(t);
}
foreach (Action t in list)
{
t();
}
Console.ReadLine();
}
}

当然运行后结果还是5,5,5,5,5

其实这段代码所演示的就是一个闭包对象。所谓的闭包对象,指的是上面这种情形中的TempClass对象,如果匿名方法(Lambda表达式)引用了某个局部变量,编译器就会自动将该引用提升到该闭包对象中,即将for循环中的变量i修改成了引用闭包对象的公共变量i。这样一来,即使代码执行后离开了原局部变量i的作用域(如for循环),包含该闭包对象的作用域也还存在。

下面简单修改一下之前的代码

    class Program
{ static void Main(string[] args)
{
List<Action> list = new List<Action>();
for (int i = ; i < ; i++)
{
int temp = i;
Action t = () => Console.WriteLine(temp.ToString());
list.Add(t);
}
foreach (Action t in list)
{
t();
}
Console.ReadLine();
}
}

执行结果如下:

建议39、了解委托的实质

http://www.cnblogs.com/aehyok/archive/2013/03/22/2976356.html这里有我之前对委托的简单的学习过程,虽然在工作中很少用,几乎就没用。不过还是拿来学习学习。

理解委托需要把握两个点:

1、委托是方法指针。

2、委托就是一个类。当对其进行实例化的时候,要将引用方法作为它构造函数的参数。

建议40、使用event关键字对委托施加保护

http://www.cnblogs.com/aehyok/archive/2013/02/22/2922586.html 这也是对于事件的简单理解学习。

建议41、实现标准的事件模型

我们应该知道微软为事件模型设定的几个规范:

1、委托类型的名称以EventHandler结束。

2、委托原型返回值为void。

3、委托原型具有两个参数:sender表示事件触发者,e表示事件参数。

4、事件参数的名称以EventArgs结束。

    public class FileUploadedEventArgs : EventArgs
{
public int FileProgress { get; set; }
} public class FileUploader
{
public event EventHandler<FileUploadedEventArgs> FileUploaded; public void Upload()
{
FileUploadedEventArgs e = new FileUploadedEventArgs() { FileProgress= };
while (e.FileProgress > )
{
///传输代码,省略
e.FileProgress--;
if (FileUploaded != null)
{
FileUploaded(this, e);
}
}
}
}

最终进行调用的代码如下:

    class Program
{
static void Main(string[] args)
{
FileUploader fileUploader = new FileUploader();
fileUploader.FileUploaded += Progress;
fileUploader.Upload();
Console.ReadLine();
} static void Progress(object sender,FileUploadedEventArgs e)
{
Console.WriteLine(e.FileProgress);
}
}

英语小贴士

1、Hello. This is United Airlines.——联合航空,您好。  I'd like to reconfirm my flight.——我想要再确认班机。

2、What's your name and flight number?——请说您的大名与班机号码?  

3、My name is Jerry Cheng, and the flight number is UA 003 for Los Angeles.——我的名字是杰瑞‧陈,班机号码是飞往洛杉机的联合航空003班机。

4、When is it?June 10th.——行程是那一天?6月10日。

5、I'd like to make sure of the time it leaves.——我想要确认班机时间没有改变。

6、I can't find your name. Really?——我找不到您的大名。真的?  May I have your name again?——请再告诉我一次您的大名?

7、I still can't find your name on the reservation list.——我仍然无法在订位名单中找到您的名字。

8、Anyway, we have seats for new bookings on this flight. No problem.——别担心,这班班机仍有空位提供新的订位者。

9、One economy class seat, is that right?——一个经济舱座位,对吗?  Now you have been booked.——没问题,您已完成订位。

10、Thanks a lot. What time do you start check-in?——谢谢。你们何时开始办理登机?

11、Two hours before departure time.——起飞前2小时。  You must check-in at least one hour before.——你必须在至少1小时前办理登机。

作者:aehyok

出处:http://www.cnblogs.com/aehyok/

感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,那不妨点个推荐吧,谢谢支持:-O。

编写高质量代码改善C#程序的157个建议[C#闭包的陷阱、委托、事件、事件模型]的更多相关文章

  1. 编写高质量代码改善C#程序的157个建议[1-3]

    原文:编写高质量代码改善C#程序的157个建议[1-3] 前言 本文主要来学习记录前三个建议. 建议1.正确操作字符串 建议2.使用默认转型方法 建议3.区别对待强制转换与as和is 其中有很多需要理 ...

  2. 读书--编写高质量代码 改善C#程序的157个建议

    最近读了陆敏技写的一本书<<编写高质量代码  改善C#程序的157个建议>>书写的很好.我还看了他的博客http://www.cnblogs.com/luminji . 前面部 ...

  3. 编写高质量代码改善C#程序的157个建议——建议157:从写第一个界面开始,就进行自动化测试

    建议157:从写第一个界面开始,就进行自动化测试 如果说单元测试是白盒测试,那么自动化测试就是黑盒测试.黑盒测试要求捕捉界面上的控件句柄,并对其进行编码,以达到模拟人工操作的目的.具体的自动化测试请学 ...

  4. 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本

    建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...

  5. 编写高质量代码改善C#程序的157个建议——建议155:随生产代码一起提交单元测试代码

    建议155:随生产代码一起提交单元测试代码 首先提出一个问题:我们害怕修改代码吗?是否曾经无数次面对乱糟糟的代码,下决心进行重构,然后在一个月后的某个周一,却收到来自测试版的报告:新的版本,没有之前的 ...

  6. 编写高质量代码改善C#程序的157个建议——建议154:不要过度设计,在敏捷中体会重构的乐趣

    建议154:不要过度设计,在敏捷中体会重构的乐趣 有时候,我们不得不随时更改软件的设计: 如果项目是针对某个大型机构的,不同级别的软件使用者,会提出不同的需求,或者随着关键岗位人员的更替,需求也会随个 ...

  7. 编写高质量代码改善C#程序的157个建议——建议153:若抛出异常,则必须要注释

    建议153:若抛出异常,则必须要注释 有一种必须加注释的场景,即使异常.如果API抛出异常,则必须给出注释.调用者必须通过注释才能知道如何处理那些专有的异常.通常,即便良好的命名也不可能告诉我们方法会 ...

  8. 编写高质量代码改善C#程序的157个建议——建议152:最少,甚至是不要注释

    建议152:最少,甚至是不要注释 以往,我们在代码中不写上几行注释,就会被认为是钟不负责任的态度.现在,这种观点正在改变.试想,如果我们所有的命名全部采用有意义的单词或词组,注释还有多少存在的价值. ...

  9. 编写高质量代码改善C#程序的157个建议——建议151:使用事件访问器替换公开的事件成员变量

    建议151:使用事件访问器替换公开的事件成员变量 事件访问器包含两部分内容:添加访问器和删除访问器.如果涉及公开的事件字段,应该始终使用事件访问器.代码如下所示: class SampleClass ...

随机推荐

  1. visual studio 2013 快捷键大全

    1.回到上一个光标位置/前进到下一个光标位置 1)回到上一个光标位置:使用组合键“Ctrl + -”: 2)前进到下一个光标位置:“Ctrl + Shift + - ”. 2.复制/剪切/删除整行代码 ...

  2. CI 框架中的自定义路由规则

    在 CI 框架中,一个 URL 和它对应的控制器中的类以及类中的方法是一一对应的,如: www.test.com/user/info/zhaoyingnan 其中 user 对应的就是控制器中的 us ...

  3. Python的逻辑运算符and小析

    近期突然对验证码的识别感兴趣了,然后就研究了一些图像识别和处理的资料,其中有一种图像处理是关于字体的细化和骨架提取的,但是这种算法没有现成的java代码实现,那些号称的java版代码多半都是效果很差或 ...

  4. 观nginx与lvs负载均衡的较量

    在技术工作者中,常用到的就是lvs负载均衡和Nginx负载均衡了.这两者也是比较普及的.那么,根据不同的需求,两者存在着不同的优势.具体选择哪一个,还要看您的要求了.那么我们在此为大家分享一篇文章,对 ...

  5. HTable和HTablePool使用注意事项

    HTable和HTablePool都是HBase客户端API的一部分,可以使用它们对HBase表进行CRUD操作.下面结合在项目中的应用情况,对二者使用过程中的注意事项做一下概括总结. HTable ...

  6. 通过CDC获取 HDC

    通过CDC获取HDC 通过CDC(设备描述表)获取HDC(设备上下文句柄)的方法: //第一种 void ...::OnDraw(CDC *pDC) { ...... HDC hDC=pDC-> ...

  7. POJ 2186 Popular Cows --强连通分量

    题意:给定一个有向图,问有多少个点由任意顶点出发都能达到. 分析:首先,在一个有向无环图中,能被所有点达到点,出度一定是0. 先求出所有的强连通分支,然后把每个强连通分支收缩成一个点,重新建图,这样, ...

  8. ZooKeeper一二事 - 搭建ZooKeeper伪分布式及正式集群 提供集群服务

    集群真是好好玩,最近一段时间天天搞集群,redis缓存服务集群啦,solr搜索服务集群啦,,,巴拉巴拉 今天说说zookeeper,之前搭建了一个redis集群,用了6台机子,有些朋友电脑跑步起来,有 ...

  9. Windows系统安装Oracle 11g数据库

    一.下载 http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html以下两网址来源此官方下载页 ...

  10. webBroser获取cookie

    //取当前webBrowser登录后的Cookie值 [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError ...