前言

本文已更新至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. 网站日志实时分析工具GoAccess使用

    网站日志实时分析工具GoAccess使用 系统环境CentOS release 5.5 (Final) GoAccess是一款开源的网站日志实时分析工具. GoAccess 的工作方式就是读取和解析 ...

  2. NOIP2008 普及组T4 立体图 解题报告-S.B.S.(施工未完成)

    题目描述 小渊是个聪明的孩子,他经常会给周围的小朋友们将写自己认为有趣的内容.最近,他准备给小朋友们讲解立体图,请你帮他画出立体图. 小渊有一块面积为m*n的矩形区域,上面有m*n个边长为1的格子,每 ...

  3. uva 839 Not so Mobile-S.B.S.

    Before being an ubiquous communications gadget, a mobilewas just a structure made of strings and wir ...

  4. 用c/c++混合编程方式为ios/android实现一个自绘日期选择控件(一)

    本文为原创,如有转载,请注明出处:http://www.cnblogs.com/jackybu 前言 章节: 1.需求描述以及c/c++实现日期和月历的基本操作 2.ios实现自绘日期选择控件 3.a ...

  5. 【Javascript Demo】移动端访问PC端网页时跳转到对应的移动端网页

    不想通过CSS自适应在PC端和移动端分别显示不同的样式,那么只能通过在移动端访问PC端网页时跳转到对应的移动端网页了,那么怎么跳转呢,网上也有很多文章说明,下面是本人测试有效的方式. 1.效果图 PC ...

  6. 深度优先搜索 codevs 1065 01字符串

    codevs 1065 01字符串  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 输出仅有0和1组成的长度为n的字符串,并且 ...

  7. Dijkstra求最短路径

    单源点的最短路径问题:给定带权有向图G和源点V,求从V到G中其余各顶点的最短路径 Dijkstra算法描述如下: (1)用带权的邻接矩阵arcs表示有向图,arcs[i][j]表示弧<vi,vj ...

  8. HDU 3600 Simple Puzzle 归并排序 N*N数码问题

    先介绍八数码问题: 我们首先从经典的八数码问题入手,即对于八数码问题的任意一个排列是否有解?有解的条件是什么? 我在网上搜了半天,找到一个十分简洁的结论.八数码问题原始状态如下: 1 2 3 4 5 ...

  9. 给vs2010安装上cocos2d-x的模版

    开发环境:OS(WINDOWS 8.1 X64 企业版) cocos2d-x 2.2.1  vs2010 想给vs安装上cocos的模版,执行InstallWizardForVS2010.js,老是提 ...

  10. View (三) 视图绘制流程完全解析

    相 信每个Android程序员都知道,我们每天的开发工作当中都在不停地跟View打交道,Android中的任何一个布局.任何一个控件其实都是直接或间 接继承自View的,如TextView.Butto ...