﻿<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>雨迹轩</title>
	<atom:link href="http://www.liurain.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.liurain.com</link>
	<description>一个记录我成长的地方</description>
	<lastBuildDate>Sun, 20 May 2012 14:54:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>[周结]2012.5.14-5.20 不要有任何期待</title>
		<link>http://www.liurain.com/?p=442</link>
		<comments>http://www.liurain.com/?p=442#comments</comments>
		<pubDate>Sun, 20 May 2012 12:08:00 +0000</pubDate>
		<dc:creator>雨狮</dc:creator>
				<category><![CDATA[生活点滴]]></category>
		<category><![CDATA[博客]]></category>
		<category><![CDATA[工作]]></category>
		<category><![CDATA[情感]]></category>
		<category><![CDATA[感悟]]></category>
		<category><![CDATA[生活]]></category>

		<guid isPermaLink="false">http://www.liurain.com/?p=442</guid>
		<description><![CDATA[工作： 本周完成了新软件结构中Map组件添加，以及移动、选择、矩形选择、圆形选择、放大、缩小、打开地图文件、图层管理的功能和相应工具的添加，周五在国小雄同学的帮助下也把回放部分中相关的数据结构及获取流程大致了解了一遍，总算是有底了。 现在在这个地方已经进入了走一步算一步的阶段，看着中高层一次次的开会，每次路过会议室都觉得好笑，任凭他们规划的如何宏伟，真正去实现他们想法的不是他们自己，而是屈指可数的我们几个程序员，而每次我们跟他们说如何难实现的时候，在他们左一句“很简单”右一句很理想化的实施方案后，我们也再无力争辩什么，任凭我们提出怎样的难题他们总会跳脱出我们的技术范畴相当然的认为应该这样做。这样的困局有一个很现实的话做比喻：不要试图和一个SB理论，因为他们会把你拉到和他同一个水平线，然后用丰富的经验打败你！ &#160; 生活： 周六下午被于小延同学叫出去打桌球，期间又提到了敏感人物。晚上我们又去找小黑夫妇俩聊天，同样也是把这个对我来说的敏感人物做为话题。现在真的是很少和她联系了，偶尔工作的时候看看她在线的头像，然后心里默默的告诉自己：喜欢的那个人还在，仅此而已。可他们一直在后面拱，而自己又因为那次的失败裹足不前，这样夹在中间感觉很奇怪。现在一次又一次的告诫自己：一切随缘，不要有任何的期待。现在只想好好的培养自己的其他兴趣，好好的把自己的道路规划清楚，好好的赚钱攒钱……什么都期待，但绝对不敢期待爱情。]]></description>
			<content:encoded><![CDATA[<p><strong><font color="#0000ff">工作：</font></strong></p>
<p align="center"><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.20-1.jpg" /></p>
<p style="text-indent: 2em">本周完成了新软件结构中Map组件添加，以及移动、选择、矩形选择、圆形选择、放大、缩小、打开地图文件、图层管理的功能和相应工具的添加，周五在国小雄同学的帮助下也把回放部分中相关的数据结构及获取流程大致了解了一遍，总算是有底了。</p>
<p style="text-indent: 2em">现在在这个地方已经进入了走一步算一步的阶段，看着中高层一次次的开会，每次路过会议室都觉得好笑，任凭他们规划的如何宏伟，真正去实现他们想法的不是他们自己，而是屈指可数的我们几个程序员，而每次我们跟他们说如何难实现的时候，在他们左一句“很简单”右一句很理想化的实施方案后，我们也再无力争辩什么，任凭我们提出怎样的难题他们总会跳脱出我们的技术范畴相当然的认为应该这样做。这样的困局有一个很现实的话做比喻：不要试图和一个SB理论，因为他们会把你拉到和他同一个水平线，然后用丰富的经验打败你！</p>
<p>&#160;</p>
<p><font color="#0000ff"><strong>生活：</strong></font></p>
<p align="center"><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.20-2.jpg" /></p>
<p style="text-indent: 2em">周六下午被于小延同学叫出去打桌球，期间又提到了敏感人物。晚上我们又去找小黑夫妇俩聊天，同样也是把这个对我来说的敏感人物做为话题。现在真的是很少和她联系了，偶尔工作的时候看看她在线的头像，然后心里默默的告诉自己：喜欢的那个人还在，仅此而已。可他们一直在后面拱，而自己又因为那次的失败裹足不前，这样夹在中间感觉很奇怪。现在一次又一次的告诫自己：一切随缘，不要有任何的期待。现在只想好好的培养自己的其他兴趣，好好的把自己的道路规划清楚，好好的赚钱攒钱……什么都期待，但绝对不敢期待爱情。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liurain.com/?feed=rss2&#038;p=442</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[周结]2012.5.7-5.13 人懒，心累，事多</title>
		<link>http://www.liurain.com/?p=440</link>
		<comments>http://www.liurain.com/?p=440#comments</comments>
		<pubDate>Sun, 13 May 2012 14:53:00 +0000</pubDate>
		<dc:creator>雨狮</dc:creator>
				<category><![CDATA[生活点滴]]></category>
		<category><![CDATA[博客]]></category>
		<category><![CDATA[工作]]></category>
		<category><![CDATA[情感]]></category>
		<category><![CDATA[感悟]]></category>
		<category><![CDATA[生活]]></category>

		<guid isPermaLink="false">http://www.liurain.com/?p=440</guid>
		<description><![CDATA[&#160; 工作： 本周开始进行新项目的整合，仔细看了下感觉如果自己全身心的投入，整合的过程应该没自己想想中的那么困难，但这周下来就是感觉整个人精神涣散的很，总是在迷迷糊糊中度过一天又一天。周五一整天参加了部门中层的一个会，主要就软件基本功能的改善，以及后期的一些开发方向进行讨论，而在最后也讨论总结出很多我们现实中遇到的问题。可是真正有能力能去解决这些问题的并非我们，而是公司的高层领导，但话说回来要能解决早就解决了，也不会如此的日积月累。这不，刚制定并在执行的五月份的计划，又要因为北京地区的部署而再次打乱，开发的人2双手都能数的过来，一面要进行新版本、新需求的开发，另一面又要就不同地区进行相应的版本生成，然后给的薪水随着时间的推移越来越不令人满意，如此的恶性循环下去，我看着都挺伤神的。 看上面怎么办吧，他们爱干嘛干嘛，我继续自己的计划！ &#160; 生活： 这个月的花销超预算有点多，不是买衣服就是为自己身体的改善做投入，钱就那么点，可欲望不断增长，不知什么时候会进入崩盘的节奏。原以为能在股市上赚点零花钱，谁知道这个又是一个坑，以为一定会涨的，总是坚挺了一阵后倒头向下，忍痛割肉后它的走势又莫名其妙的好，难道真没在股海翻腾的命？ 本来制定的5月份的计划，周初保持的还挺好的，可后面开始就慢慢的懒得无法执行，锻炼因为没把握度导致浑身疼痛无法继续，说好的练字又因为看电视太投入而忘记执行，最重要的是看java的内容是一点都没去做，现在想想真有点惭愧。又时候总觉得自己特欠抽，抱负远大，但却一次又一次的倒在“始于足下”。都不知道怎么说自己好了。]]></description>
			<content:encoded><![CDATA[<p>&#160;</p>
<p><font color="#0000ff"><strong>工作：</strong></font></p>
<p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://www.liurain.com/upload/2012/05/2012.5.13-1.jpg" /></p>
<p style="text-indent: 2em">本周开始进行新项目的整合，仔细看了下感觉如果自己全身心的投入，整合的过程应该没自己想想中的那么困难，但这周下来就是感觉整个人精神涣散的很，总是在迷迷糊糊中度过一天又一天。周五一整天参加了部门中层的一个会，主要就软件基本功能的改善，以及后期的一些开发方向进行讨论，而在最后也讨论总结出很多我们现实中遇到的问题。可是真正有能力能去解决这些问题的并非我们，而是公司的高层领导，但话说回来要能解决早就解决了，也不会如此的日积月累。这不，刚制定并在执行的五月份的计划，又要因为北京地区的部署而再次打乱，开发的人2双手都能数的过来，一面要进行新版本、新需求的开发，另一面又要就不同地区进行相应的版本生成，然后给的薪水随着时间的推移越来越不令人满意，如此的恶性循环下去，我看着都挺伤神的。</p>
<p>看上面怎么办吧，他们爱干嘛干嘛，我继续自己的计划！</p>
<p>&#160;</p>
<p><font color="#0000ff"><strong>生活：</strong></font></p>
<p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://www.liurain.com/upload/2012/05/2012.5.13-2.jpg" /></p>
<p style="text-indent: 2em">这个月的花销超预算有点多，不是买衣服就是为自己身体的改善做投入，钱就那么点，可欲望不断增长，不知什么时候会进入崩盘的节奏。原以为能在股市上赚点零花钱，谁知道这个又是一个坑，以为一定会涨的，总是坚挺了一阵后倒头向下，忍痛割肉后它的走势又莫名其妙的好，难道真没在股海翻腾的命？</p>
<p v="v">本来制定的5月份的计划，周初保持的还挺好的，可后面开始就慢慢的懒得无法执行，锻炼因为没把握度导致浑身疼痛无法继续，说好的练字又因为看电视太投入而忘记执行，最重要的是看java的内容是一点都没去做，现在想想真有点惭愧。又时候总觉得自己特欠抽，抱负远大，但却一次又一次的倒在“始于足下”。都不知道怎么说自己好了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liurain.com/?feed=rss2&#038;p=440</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>李承鹏：写在5.12的爱国帖</title>
		<link>http://www.liurain.com/?p=437</link>
		<comments>http://www.liurain.com/?p=437#comments</comments>
		<pubDate>Sat, 12 May 2012 11:59:00 +0000</pubDate>
		<dc:creator>雨狮</dc:creator>
				<category><![CDATA[百家争鸣]]></category>
		<category><![CDATA[转载]]></category>

		<guid isPermaLink="false">http://www.liurain.com/?p=437</guid>
		<description><![CDATA[那年油菜花比往年晚开了整整一个月，人们并没有意识到什么。那时人们还相信专家，专家说花期推迟很正常，青蛙上街很正常。那天我正在书房赶一篇文章，地动时还以为家猫在脚下调皮。直到满书架的书往外飞，才明白是地震。 大楼摇晃、灯杆倾斜、天边发出异光，总之那个景象十分特殊，像末日降临。我拼命冲下楼，地面像煮沸了一样抖动，地面下像有无数双手在抓脚后跟，好容易跟一些邻居逃到小区外空地……慢慢地才知道都江堰死了很多人，北川已封路了，血浆都不够用了。那时我正处于一个爱国青年的尾声，纠结处热情最为猛烈，我认为报效国家的时候到了，要用我们的血肉筑起新的长城。我在头晚到处张罗捐款后，次日清晨与唐建光、郑褚进到北川。 &#160; 可是，我在北川一中面临着人生很大的一个困扰。我无法解释为什么五层高的新楼倒塌后只有半个篮球场那么大，而几十年前修的旧楼竟没有倒塌。我也无法解释为什么楼房脆得像饼干一样且建渣里面没什么钢筋，连一楼的学生都没来得及逃脱。一个妇人一直在我身边走来走去，她已不太哭得出声，只指着那堆很渺小的建渣：看，那是我娃娃呀，手还在动，她还没死，但是我扯不出来她啊……那个情景令人崩溃，我看得见那个女娃娃碎花衣服的一角，还有其他孩子的衣角，他们中很多还在动，可按部队命令我们不能上前，因为过脆的废墟不能轻易站人，否则会引起二次崩塌。就这样眼看孩子们的身体还在动，与那些石头一起，慢慢变冷，而我们无能为力。 在此之前我还是个爱国青年，我相信生活的很多不幸是敌对势力造成的。我在球评里写“大刀向鬼子头上砍去”，这些总打败中国队的家伙是南京大屠杀的后裔。我骂过CNN长了口蹄疫，因为蒂弗莱说中国人几千年来都是暴民和垃圾。我也不反对抵制家乐福，觉得这一个侧面也可唤醒民主意识。我家离美领馆很近，99年美国导弹轰炸我驻南大使馆时，我也在美领馆外高举过抗议的拳头。同年前往美国采访时，我写过一句“像一枚导弹打进美国本土”，深觉这句子十分有力。 可站在北川学校废墟前，我很困惑。我还坚持过去一些爱国观点，但开始明白建渣里的钢筋并不是帝国主义悄悄抽走的，那些孩子也不是死于侵略者的魔爪，而死于自己人的脏手。我更困惑的是，为什么911死难者都有名字，而我们的孩子没有名字。我认为我们当然要用血肉筑起新的长城，可另一方面，长城也应该要保护我们的血肉。爱国主义应该是双向的，单向收费的不是爱国主义，是向君主效忠。 我从2008发生变化，如果晚年写自传，我会以2008为基点，在此之前我是一个混蛋。那段时间与其他一些志愿者天天在北川山里晃，救了一些老人和小孩，无意发现有一所希望小学远好无损甚至连玻璃窗都没怎么震碎，最后学生们在老师带领下翻过三座大山逃到山外。我问过校长和老师为什么出现这个奇迹，他们说得感谢那个监工。那个监工是捐款企业派来的，工程兵出身，修建过程中天天用小锤子敲水泥柱子听声音，他能从声音里听出有没有多掺沙子，圆石比例、水泥标号是否匹配，如果不合格就责令返工。老师告诉我，那些日子工地上除了施工声音就是这个监工跟人吵架的声音，除因质量问题吵，就因向当地政府追款吵。因为，企业捐助希望小学的款都要先交当地政府掌握，再由政府拨给具体施工单位……最后一架是关于操场的，终于成功追款修起了操场。大地震发生时，正是这个操场庇护了几百名孩子。 &#160; 我问过这所希望小学是不是用了特殊标准才修得这么坚固。这个监工说：不，只是按国家普通建筑标准修建的。我又得知，这个监工监理了五所学校，在那场大地震中奇迹般地无一垮塌。他说：没什么奇迹，所谓奇迹，就是你修房子时，能在十年之前想到十年之后的事情。 可是他从来不能被主流媒体宣传，名字也一直不能公布，后又传出他所属的企业其实涉黑。前两年的一天晚上，他打来电话，说正在被精神病医生治疗着，老婆也离婚了，他现在想带着女儿逃出四川，问我能不能帮他远离这是非之地，在北方找一个工作……后来我们就断了联系。 我从2008年开始变化，一个人生平第一次看到无数的冤魂，肯定会变化。我持续四年的困惑：我们不仅不能公布那些死去孩子的名字，也不能公布救了很多孩子的监工的名字。今天是汶川大震四周年，这里正式公布他的名字：句艳东。 最近大家很爱谈爱国主义。在我看来，不要狭隘理解爱国主义就是敢于抵御外敌，爱国主义更是敢于抗争内贼，这如同你爱你们村，不仅表现在敢于同别村抢水源时打架，更表现平时勤恳耕种、爱护资源、不对本村妇女耍流氓……一方面欺负本村人民，一方面为了财主利益勇敢跟别村打架，这不叫爱国主义，这叫勇当家丁。所以我认为句艳东是十足的爱国者，他没去攻打钓鱼岛黄岩岛，可他救了很多孩子，他应当得到彰显，可弘扬名望的舞台被骗子占领着，我在灾区一月见闻，多少骗子假太阳光辉之名横行……我们深爱的国家正在逆淘汰、逆宣传、逆袭真相，如果一个国家的爱国主义宣传着一些骗子，这个爱国主义本身就是骗局。 5.13下午再次强烈余震，接命令必须外撤，走了几公里撤到山口时正碰到央视张泉灵在时空连线，无意中我一身雨水的形象被摄进镜头。刚到山下，一个素以厚道著称的央视记者打来电话：你丫真会出风头，没事儿你跑北川干嘛呀，抢我们台镜头。我说：日你妈。绝交至今。一月后回京碰一著名央视仁义大哥。聊起豆腐渣工程，我说：贪官该杀几个。仁义大哥深邃地看着我：不，中国的事情要慢慢来，否则又会乱，毕竟重建还要靠他们呀。又过三年，我不小心批评了倪萍“共和国脊梁”，该名仁义大哥电话里斥：你丫骂人倪大姐干什么呢，她可是好人哪。我在香港书展调侃于丹余秋雨伪善，仁义大哥再斥：想不到这几年你变成这种人，承鹏，咱不能只破坏不建设，不能见政府干的事都是错的。 我曾经如此欣赏仁义大哥，现在大家天各一方，形同陌路。他那些不知是矫造还是表演的关于公平正义的话在微博流传着，星光灿烂，粉丝推崇。以及类似仁义大哥这样的爱国者总说：不管国家有这样或那样的问题，可我们仍要爱这个国。我觉得这是个病句，我爱这个国，可我不能去爱制造豆腐渣工程的政府，更不能去爱给学校修豆腐渣给自己修豪华办公楼的政府官员。 我认为我仍是一个爱国者，可历经2008年的奥运、毒牛奶特别是汶川大地震，我对爱国主义重新定义。爱国主义肯定不是一边说是外人抢劫了我们，一边亲自掠夺国人财富的主义；不是一边说恶邻让我们石油紧缺，一边派出发改委只涨不降的主义；不是一边号召不要让强盗欺负我们的母亲，一边在大地震里让很多的母亲被欺侮的主义，她们看得见自己孩子的手还在动，却无能为力。那天我发了一条很爱国的微博：爱国主义就是，你并不拥有一寸私土，却宣称用生命保卫这片领土。这情形就像你并不在银行里拥有一分存款，却宣布誓死捍卫里面的金库……而且，此时你并不知道劫匪在哪里，银行保安是否把你当成劫匪。 &#160; 这条微博伤害了很多爱国者的感情，纷纷斥责我为汉奸。我认为这又是个病句，在中国官不至厅局级，财产不过一个亿，每年不去开几个峰会哪好意思夸自己是汉奸。又说我是带路党，可是不拿几张绿卡儿女不开着法拉利在名校上学不在美国置几处房产哪有资格带路。还有说，母亲无论怎样打骂过我们，可毕竟是生我养我的亲妈啊。我就突然想起爱国者曲啸了——尼玛谁见过这么下毒手打骂自己孩子的亲妈？ 我其实相当地不反对打黄岩的，可反对只打黄岩不打黄贼。可爱国者逻辑是：打黄贼得给政府一些时间，打黄岩迫不及待。对此我只有一个解析：多少黄贼，假打黄岩之名逃于法网之外。就想起五四运动中的梅思平，假爱国之名火烧曹家，可日本人打来时第一批参加了汪伪政府。 这样比爱国主义胸大肌其实很难证明真伪，说实话这三十年中国实力取得不小进步，至少近期不太可能有大批日本鬼子打进家门，所以那些组织义勇军半夜去炸碉堡的行为基本属于自我催眠的英雄幻想，不如让我们谈谈务实的爱国主义：爱国主义是给孩子修校舍时少一分回扣，多几根钢筋；爱国主义是少修点豪华办公楼，多建些实用农舍；爱国主义是少喝点爱心茅台，多吐槽些醒世真言；爱国主义是少宣传些虚假的英雄，多公布些逝去的名字；爱国主义是能让国民在这个国自由迁徙、念书，而不是平民子弟五证齐全才能就读京城；爱国主义爱的不是国家专政机器，而是去爱一种共同价值观……重要的不是拥护广袤的领土，更重要的是拥有生活的尊严。 小小黄岩，以我军威武几排炮就打成粉齑，收回失地指日可待，以壮国威；重重汶川，多少魂灵在飞，不惩前毖后，君将空负民心。 我是一个爱国者，所以，我在乎庞大的领土多一个小岛的名字，更在乎小小的纪念碑上回归数万亡灵的真实姓名——是为写在5.12的爱国帖。]]></description>
			<content:encoded><![CDATA[<p align="center"><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.12-1.jpg" /></p>
<p style="text-indent: 2em">那年油菜花比往年晚开了整整一个月，人们并没有意识到什么。那时人们还相信专家，专家说花期推迟很正常，青蛙上街很正常。那天我正在书房赶一篇文章，地动时还以为家猫在脚下调皮。直到满书架的书往外飞，才明白是地震。</p>
<p style="text-indent: 2em">大楼摇晃、灯杆倾斜、天边发出异光，总之那个景象十分特殊，像末日降临。我拼命冲下楼，地面像煮沸了一样抖动，地面下像有无数双手在抓脚后跟，好容易跟一些邻居逃到小区外空地……慢慢地才知道都江堰死了很多人，北川已封路了，血浆都不够用了。那时我正处于一个爱国青年的尾声，纠结处热情最为猛烈，我认为报效国家的时候到了，要用我们的血肉筑起新的长城。我在头晚到处张罗捐款后，次日清晨与唐建光、郑褚进到北川。</p>
<p style="text-indent: 2em">&#160;</p>
<p align="center"><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.12-2.jpg" /></p>
<p style="text-indent: 2em">可是，我在北川一中面临着人生很大的一个困扰。我无法解释为什么五层高的新楼倒塌后只有半个篮球场那么大，而几十年前修的旧楼竟没有倒塌。我也无法解释为什么楼房脆得像饼干一样且建渣里面没什么钢筋，连一楼的学生都没来得及逃脱。一个妇人一直在我身边走来走去，她已不太哭得出声，只指着那堆很渺小的建渣：看，那是我娃娃呀，手还在动，她还没死，但是我扯不出来她啊……那个情景令人崩溃，我看得见那个女娃娃碎花衣服的一角，还有其他孩子的衣角，他们中很多还在动，可按部队命令我们不能上前，因为过脆的废墟不能轻易站人，否则会引起二次崩塌。就这样眼看孩子们的身体还在动，与那些石头一起，慢慢变冷，而我们无能为力。</p>
<p style="text-indent: 2em">在此之前我还是个爱国青年，我相信生活的很多不幸是敌对势力造成的。我在球评里写“大刀向鬼子头上砍去”，这些总打败中国队的家伙是南京大屠杀的后裔。我骂过CNN长了口蹄疫，因为蒂弗莱说中国人几千年来都是暴民和垃圾。我也不反对抵制家乐福，觉得这一个侧面也可唤醒民主意识。我家离美领馆很近，99年美国导弹轰炸我驻南大使馆时，我也在美领馆外高举过抗议的拳头。同年前往美国采访时，我写过一句“像一枚导弹打进美国本土”，深觉这句子十分有力。</p>
<p style="text-indent: 2em">可站在北川学校废墟前，我很困惑。我还坚持过去一些爱国观点，但开始明白建渣里的钢筋并不是帝国主义悄悄抽走的，那些孩子也不是死于侵略者的魔爪，而死于自己人的脏手。我更困惑的是，为什么911死难者都有名字，而我们的孩子没有名字。我认为我们当然要用血肉筑起新的长城，可另一方面，长城也应该要保护我们的血肉。爱国主义应该是双向的，单向收费的不是爱国主义，是向君主效忠。</p>
<p style="text-indent: 2em">我从2008发生变化，如果晚年写自传，我会以2008为基点，在此之前我是一个混蛋。那段时间与其他一些志愿者天天在北川山里晃，救了一些老人和小孩，无意发现有一所希望小学远好无损甚至连玻璃窗都没怎么震碎，最后学生们在老师带领下翻过三座大山逃到山外。我问过校长和老师为什么出现这个奇迹，他们说得感谢那个监工。那个监工是捐款企业派来的，工程兵出身，修建过程中天天用小锤子敲水泥柱子听声音，他能从声音里听出有没有多掺沙子，圆石比例、水泥标号是否匹配，如果不合格就责令返工。老师告诉我，那些日子工地上除了施工声音就是这个监工跟人吵架的声音，除因质量问题吵，就因向当地政府追款吵。因为，企业捐助希望小学的款都要先交当地政府掌握，再由政府拨给具体施工单位……最后一架是关于操场的，终于成功追款修起了操场。大地震发生时，正是这个操场庇护了几百名孩子。</p>
<p style="text-indent: 2em">&#160;</p>
<p align="center"><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.12-3.jpg" /></p>
<p style="text-indent: 2em">我问过这所希望小学是不是用了特殊标准才修得这么坚固。这个监工说：不，只是按国家普通建筑标准修建的。我又得知，这个监工监理了五所学校，在那场大地震中奇迹般地无一垮塌。他说：没什么奇迹，所谓奇迹，就是你修房子时，能在十年之前想到十年之后的事情。</p>
<p style="text-indent: 2em">可是他从来不能被主流媒体宣传，名字也一直不能公布，后又传出他所属的企业其实涉黑。前两年的一天晚上，他打来电话，说正在被精神病医生治疗着，老婆也离婚了，他现在想带着女儿逃出四川，问我能不能帮他远离这是非之地，在北方找一个工作……后来我们就断了联系。</p>
<p style="text-indent: 2em">我从2008年开始变化，一个人生平第一次看到无数的冤魂，肯定会变化。我持续四年的困惑：我们不仅不能公布那些死去孩子的名字，也不能公布救了很多孩子的监工的名字。今天是汶川大震四周年，这里正式公布他的名字：句艳东。</p>
<p style="text-indent: 2em">最近大家很爱谈爱国主义。在我看来，不要狭隘理解爱国主义就是敢于抵御外敌，爱国主义更是敢于抗争内贼，这如同你爱你们村，不仅表现在敢于同别村抢水源时打架，更表现平时勤恳耕种、爱护资源、不对本村妇女耍流氓……一方面欺负本村人民，一方面为了财主利益勇敢跟别村打架，这不叫爱国主义，这叫勇当家丁。所以我认为句艳东是十足的爱国者，他没去攻打钓鱼岛黄岩岛，可他救了很多孩子，他应当得到彰显，可弘扬名望的舞台被骗子占领着，我在灾区一月见闻，多少骗子假太阳光辉之名横行……我们深爱的国家正在逆淘汰、逆宣传、逆袭真相，如果一个国家的爱国主义宣传着一些骗子，这个爱国主义本身就是骗局。</p>
<p style="text-indent: 2em">5.13下午再次强烈余震，接命令必须外撤，走了几公里撤到山口时正碰到央视张泉灵在时空连线，无意中我一身雨水的形象被摄进镜头。刚到山下，一个素以厚道著称的央视记者打来电话：你丫真会出风头，没事儿你跑北川干嘛呀，抢我们台镜头。我说：日你妈。绝交至今。一月后回京碰一著名央视仁义大哥。聊起豆腐渣工程，我说：贪官该杀几个。仁义大哥深邃地看着我：不，中国的事情要慢慢来，否则又会乱，毕竟重建还要靠他们呀。又过三年，我不小心批评了倪萍“共和国脊梁”，该名仁义大哥电话里斥：你丫骂人倪大姐干什么呢，她可是好人哪。我在香港书展调侃于丹余秋雨伪善，仁义大哥再斥：想不到这几年你变成这种人，承鹏，咱不能只破坏不建设，不能见政府干的事都是错的。</p>
<p style="text-indent: 2em">我曾经如此欣赏仁义大哥，现在大家天各一方，形同陌路。他那些不知是矫造还是表演的关于公平正义的话在微博流传着，星光灿烂，粉丝推崇。以及类似仁义大哥这样的爱国者总说：不管国家有这样或那样的问题，可我们仍要爱这个国。我觉得这是个病句，我爱这个国，可我不能去爱制造豆腐渣工程的政府，更不能去爱给学校修豆腐渣给自己修豪华办公楼的政府官员。</p>
<p style="text-indent: 2em">我认为我仍是一个爱国者，可历经2008年的奥运、毒牛奶特别是汶川大地震，我对爱国主义重新定义。爱国主义肯定不是一边说是外人抢劫了我们，一边亲自掠夺国人财富的主义；不是一边说恶邻让我们石油紧缺，一边派出发改委只涨不降的主义；不是一边号召不要让强盗欺负我们的母亲，一边在大地震里让很多的母亲被欺侮的主义，她们看得见自己孩子的手还在动，却无能为力。那天我发了一条很爱国的微博：爱国主义就是，你并不拥有一寸私土，却宣称用生命保卫这片领土。这情形就像你并不在银行里拥有一分存款，却宣布誓死捍卫里面的金库……而且，此时你并不知道劫匪在哪里，银行保安是否把你当成劫匪。</p>
<p style="text-indent: 2em">&#160;</p>
<p align="center"><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.12-4.jpg" /></p>
<p style="text-indent: 2em">这条微博伤害了很多爱国者的感情，纷纷斥责我为汉奸。我认为这又是个病句，在中国官不至厅局级，财产不过一个亿，每年不去开几个峰会哪好意思夸自己是汉奸。又说我是带路党，可是不拿几张绿卡儿女不开着法拉利在名校上学不在美国置几处房产哪有资格带路。还有说，母亲无论怎样打骂过我们，可毕竟是生我养我的亲妈啊。我就突然想起爱国者曲啸了——尼玛谁见过这么下毒手打骂自己孩子的亲妈？</p>
<p style="text-indent: 2em">我其实相当地不反对打黄岩的，可反对只打黄岩不打黄贼。可爱国者逻辑是：打黄贼得给政府一些时间，打黄岩迫不及待。对此我只有一个解析：多少黄贼，假打黄岩之名逃于法网之外。就想起五四运动中的梅思平，假爱国之名火烧曹家，可日本人打来时第一批参加了汪伪政府。</p>
<p style="text-indent: 2em">这样比爱国主义胸大肌其实很难证明真伪，说实话这三十年中国实力取得不小进步，至少近期不太可能有大批日本鬼子打进家门，所以那些组织义勇军半夜去炸碉堡的行为基本属于自我催眠的英雄幻想，不如让我们谈谈务实的爱国主义：爱国主义是给孩子修校舍时少一分回扣，多几根钢筋；爱国主义是少修点豪华办公楼，多建些实用农舍；爱国主义是少喝点爱心茅台，多吐槽些醒世真言；爱国主义是少宣传些虚假的英雄，多公布些逝去的名字；爱国主义是能让国民在这个国自由迁徙、念书，而不是平民子弟五证齐全才能就读京城；爱国主义爱的不是国家专政机器，而是去爱一种共同价值观……重要的不是拥护广袤的领土，更重要的是拥有生活的尊严。</p>
<p style="text-indent: 2em">小小黄岩，以我军威武几排炮就打成粉齑，收回失地指日可待，以壮国威；重重汶川，多少魂灵在飞，不惩前毖后，君将空负民心。</p>
<p style="text-indent: 2em">我是一个爱国者，所以，我在乎庞大的领土多一个小岛的名字，更在乎小小的纪念碑上回归数万亡灵的真实姓名——是为写在5.12的爱国帖。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liurain.com/?feed=rss2&#038;p=437</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>韩寒：太平洋的风</title>
		<link>http://www.liurain.com/?p=435</link>
		<comments>http://www.liurain.com/?p=435#comments</comments>
		<pubDate>Fri, 11 May 2012 02:07:00 +0000</pubDate>
		<dc:creator>雨狮</dc:creator>
				<category><![CDATA[百家争鸣]]></category>
		<category><![CDATA[台湾]]></category>
		<category><![CDATA[转载]]></category>

		<guid isPermaLink="false">http://www.liurain.com/?p=435</guid>
		<description><![CDATA[空客320降落在桃园机场。飞机的降落把我震醒。手机里正好播放到张艾嘉的《戏雪》，这算是一首生僻的歌，陈升写下这样的词——“1948年，我离开我最爱的人，当火车开动的时候，北方正飘着苍茫的雪，如果我知道，这一别就是四十余年，岁月若能从头，我很想说，我不走。” 对于台湾，我的印象一直停留在侯孝贤和杨德昌的电影里。后来魏德胜和九把刀又加工了一下。我喜欢的作家，梁实秋，林语堂，胡适也都去了台湾，而且他们都和鲁迅吵过架。当大陆穷的时候，台湾有钱，后来大陆有钱了——确切的说，是政府和小部分人有钱了，台湾又有了…… 战火把同一个民族的人分隔在了海峡的两岸，那些具体到每个家庭的悲欢离合已经被时间慢慢抹平。台北的街道的确像优客李林唱的那样，像迷宫一样展开在我的眼前。但是对于异乡人，每个陌生的城市都是迷宫。在酒店住下，诚品书店就在旁边。朋友的眼镜架坏了，于是晚上先陪着朋友去配眼镜。我们坐计程车来到了台大附近，进了一家眼镜店。没有声音酥麻的台妹，老板亲自上阵。朋友看中了一副镜框，但要几天以后才能取。朋友说，那算了，我在台湾只留三天，我要明天就能取的，只能去别的地方看看。这时候，让我诧异的一幕出现了，老板居然从柜台里摸索出了一对隐形眼镜，塞在我朋友手里，说，实在不好意思，没能帮上你的忙，这个送你，先用这个应急吧。连我这般总是把人往好里想的人第一反应也是——我靠，哪有这种好事，这里面是有什么猫腻吧？咱还能走出这家店的店门么？ 我们平安的走出了这家眼镜店，换去了隔壁一家。那家眼镜店承诺第二天就可以把眼镜做好，然后那家店的老板用朋友残留下的镜片临时找了一个镜框凑合装了起来，告诉朋友，这个可以晚上用。这两家只是非常普通的路边眼镜店，还是自己随机找的，要不真得让人怀疑是不是组织方安排的，目的为了让大家增加对台湾的好感。 台湾的街道上有不少的小游行和抗议横幅，这一切对于大部分大陆游客来说都太新鲜了，于是很多游客守着电视机看晚上的政论节目。我妈妈去年从台湾旅游回来，就说那里太好玩了，领导人可以在电视里随便骂，比快乐大本营还要欢乐。相比之下，台湾人对这些早就习以为常。但给我留下了比马英九先生更深印象的是王鸿松先生——他不是明星政客，也不是文人墨客。他是一个计程车司机。一天早上，我从酒店下楼，打了他的车去阳明山。到了目的地我发现把手机拉在出租车上。我没有记下车牌号。朋友们忙着帮我联系出租车公司，看看能不能查到一些讯息，我也打给酒店，想让他们查看一下监控录像，确认车牌号。一会儿，我接到了酒店的电话，我问他们，是查到车号了么？他们说，监控录像里讯息太多，还没有查到，但是刚才有一位出租车司机开回酒店，把一个手机交给了前台，说是一位从你们这里上车的先生遗落在车里的。。。。。。 说实话，我石化了。我问到了出租车司机的电话和名字，说我想酬谢你。王鸿松说，不需要啦，很正常的，小事一桩，我们都是这样的。他告诉我，前几天刚和几个朋友环岛开了一圈，打算过一段时间来大陆旅行。他说他开计程车就是为了能够去更多的地方看看。末了居然还来一句：我有QQ和新浪微博的，你的号是什么，我们可以在网上联系的。这顿时让我觉得两岸关系非常亲密。接着，他继续说，你有脸书么？我说，大陆的互联网没有脸……书。他说，哦，对哦，是哦。我不和你说了，有客人了，再联系哦。 也许是我的命好，遇见的都是好人，也许是我走的肤浅，几乎所有人都和气。毫无疑问，如果我在台湾多停留几天，我当然能看见他不如人意的一面，也许他硬件不够新，也许他民粹也涌现，也许他民怨从不断，也许他矛盾也不少。没有完美的地方，没有完美的制度，没有完美的文化，在华人的世界里，它也许不是最好的，但的确没有什么比它更好了。 这篇文章里不想谈论什么政治和体制。作为一个从大陆来的写作者，我只是非常失落。这些失落并不是来自于这几天浅显的旅行，而是一直以来的感受。我失落在我生存的环境里，前几十年教人凶残和斗争，后几十年使人贪婪和自私，于是我们很多人的骨子里被埋下了这些种子；我失落在我们的前辈们摧毁了文化，也摧毁了那些传统的美德，摧毁了人与人之间的信任，摧毁了信仰和共识，却没有建立起一个美丽新世界，作为晚辈，我们谁也不知道能否弥补这一切，还是继续的摧毁下去；我失落在不知道我们的后代能不能生存在一个互相理解而不是互相伤害的环境之中；我失落在作为一个写作者，我写这篇文章的时候还要不停的考虑措辞，以免哪个地方说过了线；我失落在当他人以善意面对我的时候，我的第一反应居然是会不会有什么阴谋；我失落在我们自己的文艺作品很少能够在台湾真正流传，而能在台湾流传的关于我们的大多是那些历史真相和社会批判，更让人失落的是那些批判和揭露往往都是被我们自己买了回去，用于更加了解我们自己。除了利益和人与人之间的斗争，我们几乎对一切都冷漠。这些冷漠和荒诞所催生的新闻都被世界各地的报纸不停的放在头版，虽然可以说这是官方的错，但无奈却也成了这个民族的注释。 是的，我要感谢香港和台湾，他们庇护了中华的文化，把这个民族美好的习性留了下来，让很多根子里的东西免于浩劫。纵然他们也有着这样那样的诟病。而我们，纵然我们有了丽兹卡尔顿和半岛酒店，有了gucci和lv，我们的县长太太也许比他们最大的官员还要富有，我们随便一个大片的制作成本就够他们拍二三十部电影，我们的世博会和奥运会他们永远办不起，但走在台湾的街头，面对着那些计程车司机，快餐店老板，路人们，我却一点自豪感都没有。 文化，法制和自由是一个民族的一切，别的国家不会因为你国的富豪疯狂抢购了超级跑车和顶级游艇而尊敬你的国民。坐在空客330的机舱里，飞翔在两万英尺的高空，一个半小时就到了上海。既然我们共享着太平洋的风，就让它吹过所有的一切。]]></description>
			<content:encoded><![CDATA[<p align="center"><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.11-2.jpg" /></p>
<p style="text-indent: 2em">空客320降落在桃园机场。飞机的降落把我震醒。手机里正好播放到张艾嘉的《戏雪》，这算是一首生僻的歌，陈升写下这样的词——“1948年，我离开我最爱的人，当火车开动的时候，北方正飘着苍茫的雪，如果我知道，这一别就是四十余年，岁月若能从头，我很想说，我不走。”</p>
<p style="text-indent: 2em">对于台湾，我的印象一直停留在侯孝贤和杨德昌的电影里。后来魏德胜和九把刀又加工了一下。我喜欢的作家，梁实秋，林语堂，胡适也都去了台湾，而且他们都和鲁迅吵过架。当大陆穷的时候，台湾有钱，后来大陆有钱了——确切的说，是政府和小部分人有钱了，台湾又有了……</p>
<p style="text-indent: 2em">战火把同一个民族的人分隔在了海峡的两岸，那些具体到每个家庭的悲欢离合已经被时间慢慢抹平。台北的街道的确像优客李林唱的那样，像迷宫一样展开在我的眼前。但是对于异乡人，每个陌生的城市都是迷宫。在酒店住下，诚品书店就在旁边。朋友的眼镜架坏了，于是晚上先陪着朋友去配眼镜。我们坐计程车来到了台大附近，进了一家眼镜店。没有声音酥麻的台妹，老板亲自上阵。朋友看中了一副镜框，但要几天以后才能取。朋友说，那算了，我在台湾只留三天，我要明天就能取的，只能去别的地方看看。这时候，让我诧异的一幕出现了，老板居然从柜台里摸索出了一对隐形眼镜，塞在我朋友手里，说，实在不好意思，没能帮上你的忙，这个送你，先用这个应急吧。连我这般总是把人往好里想的人第一反应也是——我靠，哪有这种好事，这里面是有什么猫腻吧？咱还能走出这家店的店门么？</p>
<p style="text-indent: 2em">我们平安的走出了这家眼镜店，换去了隔壁一家。那家眼镜店承诺第二天就可以把眼镜做好，然后那家店的老板用朋友残留下的镜片临时找了一个镜框凑合装了起来，告诉朋友，这个可以晚上用。这两家只是非常普通的路边眼镜店，还是自己随机找的，要不真得让人怀疑是不是组织方安排的，目的为了让大家增加对台湾的好感。</p>
<p style="text-indent: 2em">台湾的街道上有不少的小游行和抗议横幅，这一切对于大部分大陆游客来说都太新鲜了，于是很多游客守着电视机看晚上的政论节目。我妈妈去年从台湾旅游回来，就说那里太好玩了，领导人可以在电视里随便骂，比快乐大本营还要欢乐。相比之下，台湾人对这些早就习以为常。但给我留下了比马英九先生更深印象的是王鸿松先生——他不是明星政客，也不是文人墨客。他是一个计程车司机。一天早上，我从酒店下楼，打了他的车去阳明山。到了目的地我发现把手机拉在出租车上。我没有记下车牌号。朋友们忙着帮我联系出租车公司，看看能不能查到一些讯息，我也打给酒店，想让他们查看一下监控录像，确认车牌号。一会儿，我接到了酒店的电话，我问他们，是查到车号了么？他们说，监控录像里讯息太多，还没有查到，但是刚才有一位出租车司机开回酒店，把一个手机交给了前台，说是一位从你们这里上车的先生遗落在车里的。。。。。。</p>
<p style="text-indent: 2em">说实话，我石化了。我问到了出租车司机的电话和名字，说我想酬谢你。王鸿松说，不需要啦，很正常的，小事一桩，我们都是这样的。他告诉我，前几天刚和几个朋友环岛开了一圈，打算过一段时间来大陆旅行。他说他开计程车就是为了能够去更多的地方看看。末了居然还来一句：我有QQ和新浪微博的，你的号是什么，我们可以在网上联系的。这顿时让我觉得两岸关系非常亲密。接着，他继续说，你有脸书么？我说，大陆的互联网没有脸……书。他说，哦，对哦，是哦。我不和你说了，有客人了，再联系哦。</p>
<p style="text-indent: 2em">也许是我的命好，遇见的都是好人，也许是我走的肤浅，几乎所有人都和气。毫无疑问，如果我在台湾多停留几天，我当然能看见他不如人意的一面，也许他硬件不够新，也许他民粹也涌现，也许他民怨从不断，也许他矛盾也不少。没有完美的地方，没有完美的制度，没有完美的文化，在华人的世界里，它也许不是最好的，但的确没有什么比它更好了。</p>
<p align="center"><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.11-1.jpg" /></p>
<p style="text-indent: 2em">这篇文章里不想谈论什么政治和体制。作为一个从大陆来的写作者，我只是非常失落。这些失落并不是来自于这几天浅显的旅行，而是一直以来的感受。我失落在我生存的环境里，前几十年教人凶残和斗争，后几十年使人贪婪和自私，于是我们很多人的骨子里被埋下了这些种子；我失落在我们的前辈们摧毁了文化，也摧毁了那些传统的美德，摧毁了人与人之间的信任，摧毁了信仰和共识，却没有建立起一个美丽新世界，作为晚辈，我们谁也不知道能否弥补这一切，还是继续的摧毁下去；我失落在不知道我们的后代能不能生存在一个互相理解而不是互相伤害的环境之中；我失落在作为一个写作者，我写这篇文章的时候还要不停的考虑措辞，以免哪个地方说过了线；我失落在当他人以善意面对我的时候，我的第一反应居然是会不会有什么阴谋；我失落在我们自己的文艺作品很少能够在台湾真正流传，而能在台湾流传的关于我们的大多是那些历史真相和社会批判，更让人失落的是那些批判和揭露往往都是被我们自己买了回去，用于更加了解我们自己。除了利益和人与人之间的斗争，我们几乎对一切都冷漠。这些冷漠和荒诞所催生的新闻都被世界各地的报纸不停的放在头版，虽然可以说这是官方的错，但无奈却也成了这个民族的注释。</p>
<p style="text-indent: 2em">是的，我要感谢香港和台湾，他们庇护了中华的文化，把这个民族美好的习性留了下来，让很多根子里的东西免于浩劫。纵然他们也有着这样那样的诟病。而我们，纵然我们有了丽兹卡尔顿和半岛酒店，有了gucci和lv，我们的县长太太也许比他们最大的官员还要富有，我们随便一个大片的制作成本就够他们拍二三十部电影，我们的世博会和奥运会他们永远办不起，但走在台湾的街头，面对着那些计程车司机，快餐店老板，路人们，我却一点自豪感都没有。</p>
<p style="text-indent: 2em">文化，法制和自由是一个民族的一切，别的国家不会因为你国的富豪疯狂抢购了超级跑车和顶级游艇而尊敬你的国民。坐在空客330的机舱里，飞翔在两万英尺的高空，一个半小时就到了上海。既然我们共享着太平洋的风，就让它吹过所有的一切。 </p>
]]></content:encoded>
			<wfw:commentRss>http://www.liurain.com/?feed=rss2&#038;p=435</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《Dream High 2》-喜欢女二胜过女主</title>
		<link>http://www.liurain.com/?p=431</link>
		<comments>http://www.liurain.com/?p=431#comments</comments>
		<pubDate>Sat, 05 May 2012 14:46:00 +0000</pubDate>
		<dc:creator>雨狮</dc:creator>
				<category><![CDATA[剧作]]></category>
		<category><![CDATA[剧评]]></category>
		<category><![CDATA[智妍]]></category>

		<guid isPermaLink="false">http://www.liurain.com/?p=431</guid>
		<description><![CDATA[八天的调休自己分配的有些欠抽，前面大把空余时间不拿来看韩剧，偏偏周六下午还有事情，竟然周五晚上通宵到周六上午11点，就为了把已经存在硬盘中有一个多月的《Dream High 2》通关。16集用了18个小时，有点极限。由于之前听说过《Dream High》的口碑，但是实在没领教过，所以这回对《Dream High 2》的评价不会受到前作的影响。 对于这部续作，我给出的评级是：★★★(全6星)。 其实当初选择下载这部韩剧,除了其前作积攒的好口碑外,还因为有喜欢的T-ara成员智妍参演,说实话有这样的美颜担当确实赏心悦目。虽说对智妍有特别的偏好，但自己还是要给这部剧的剧评定个主基调-----“女二胜过女主”。女主角的饰演者无论戏里戏外都是相当的平凡，没有出众的外貌，吸引人的身材，不知是不是角色本身的限制，也感觉不出演技的突出。看着女主角的所有遭遇以及成长，加上她外貌的几分神似，我隐约有种在回顾《我叫金三顺》的感觉：善良、可怜女因为某方面的弱势招来许多阻碍，偏偏又有白马王子有足够的才能去帮助她，然后就是一起如何克服困难，排除万难，最后在一起。剧本主线没有新意也就算了，往里面增加枝、叶我都看着蹩脚，就拿海星与Lyan(智妍饰)第一次合作出现音响事故来说，我很难接受一个乖乖可怜女还没怎么受尽挫折，就能那么快并且城府极深的去排挤Lyan这个强势角色，从这场开始我就对海星这个人非好感。反观女二号Lyan，高傲、没礼貌、倔强这些不都是用来衬托女主角的必备素材么？只是，纵观Lyan做的很多离谱的事，我真的找不出能比女主角的“偷取电池”更卑劣的，更重要的是后面面对被劈腿的情形，Lyan的成长与改变让人不得不怜惜起这么一个有些可爱、善良的女二号。编辑大人是不是给我们设置了一个隐藏彩蛋？那就是女二号其实才是真正的主角！^_^ 剧中有许多有共鸣的歌曲，最印象深刻的就是《B级人生》，请记住“梦想不是属于有才的人，而是属于有梦想的每一个人”。 &#160; 再分享些关于智妍的剧照,没办法这妹子越看越喜欢:]]></description>
			<content:encoded><![CDATA[<p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://www.liurain.com/upload/2012/05/2012.5.6-1.jpg" /></p>
<p style="text-indent: 2em">八天的调休自己分配的有些欠抽，前面大把空余时间不拿来看韩剧，偏偏周六下午还有事情，竟然周五晚上通宵到周六上午11点，就为了把已经存在硬盘中有一个多月的《Dream High 2》通关。16集用了18个小时，有点极限。由于之前听说过《Dream High》的口碑，但是实在没领教过，所以这回对《Dream High 2》的评价不会受到前作的影响。</p>
<p style="text-indent: 2em">对于这部续作，我给出的评级是：★★★(全6星)。</p>
<p style="text-indent: 2em">其实当初选择下载这部韩剧,除了其前作积攒的好口碑外,还因为有喜欢的T-ara成员智妍参演,说实话有这样的美颜担当确实赏心悦目。虽说对智妍有特别的偏好，但自己还是要给这部剧的剧评定个主基调-----“女二胜过女主”。女主角的饰演者无论戏里戏外都是相当的平凡，没有出众的外貌，吸引人的身材，不知是不是角色本身的限制，也感觉不出演技的突出。看着女主角的所有遭遇以及成长，加上她外貌的几分神似，我隐约有种在回顾《我叫金三顺》的感觉：善良、可怜女因为某方面的弱势招来许多阻碍，偏偏又有白马王子有足够的才能去帮助她，然后就是一起如何克服困难，排除万难，最后在一起。剧本主线没有新意也就算了，往里面增加枝、叶我都看着蹩脚，就拿海星与Lyan(智妍饰)第一次合作出现音响事故来说，我很难接受一个乖乖可怜女还没怎么受尽挫折，就能那么快并且城府极深的去排挤Lyan这个强势角色，从这场开始我就对海星这个人非好感。反观女二号Lyan，高傲、没礼貌、倔强这些不都是用来衬托女主角的必备素材么？只是，纵观Lyan做的很多离谱的事，我真的找不出能比女主角的“偷取电池”更卑劣的，更重要的是后面面对被劈腿的情形，Lyan的成长与改变让人不得不怜惜起这么一个有些可爱、善良的女二号。编辑大人是不是给我们设置了一个隐藏彩蛋？那就是女二号其实才是真正的主角！^_^</p>
<p style="text-indent: 2em">剧中有许多有共鸣的歌曲，最印象深刻的就是《B级人生》，请记住“梦想不是属于有才的人，而是属于有梦想的每一个人”。</p>
<p align="center"><embed src="http://player.youku.com/player.php/sid/XMzU5NzQ4Mjc2/v.swf" quality="high" width="480" height="400" align="middle" allowScriptAccess="sameDomain" allowFullscreen="true" type="application/x-shockwave-flash"></embed></p>
<p>&#160;</p>
<p>再分享些关于智妍的剧照,没办法这妹子越看越喜欢:</p>
<p align="center"><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-2.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-3.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-4.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-5.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-6.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-7.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-8.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-9.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-10.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-11.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-12.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-13.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-14.jpg" />     <br /><img style="margin: 0px" src="http://www.liurain.com/upload/2012/05/2012.5.6-15.jpg" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.liurain.com/?feed=rss2&#038;p=431</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[周结]2012.4.23-4.29 5月份开始策划走的事情</title>
		<link>http://www.liurain.com/?p=429</link>
		<comments>http://www.liurain.com/?p=429#comments</comments>
		<pubDate>Sun, 29 Apr 2012 14:42:00 +0000</pubDate>
		<dc:creator>雨狮</dc:creator>
				<category><![CDATA[生活点滴]]></category>
		<category><![CDATA[博客]]></category>
		<category><![CDATA[工作]]></category>
		<category><![CDATA[情感]]></category>
		<category><![CDATA[感悟]]></category>
		<category><![CDATA[生活]]></category>

		<guid isPermaLink="false">http://www.liurain.com/?p=429</guid>
		<description><![CDATA[工作： 本周是心情跌到谷底的一周，来了做GIS的研究生，本以为有个搭档我能解绑不用那么累，可是天不遂人愿，研究生只待了一天就不干了。这样的临时变卦也不是没遇见过，可是发生在自己身上就特能真切的体会那种感受。这其实不算什么，本周的后面几天才让我对这个公司有了彻底的失望。来了个所谓的张副总，没先到比想象中的还糟糕，他聊聊天泡泡茶不知道一整天在工作什么，对这我真有点意见，可是看到周四他下发的五月份任务清单，我才觉得他泡茶聊天真没什么，至少不会对我们工作产生影响，属于无害。现在这样瞎指挥真的让我不能忍！原来从java调到去做.NET，然后又去做缺人的研究的GIS，我已经觉得自己已经忍让到极限，现在有点眉目了竟然5月份让我去做与GIS一点都没关系的内容，这不让我前面的努力付诸东流？不能知人善任是对整个部门很伤的一个东西！而且还有意思的是他分配了任务后只是跟我们说明了下做什么以及一些其他需求，而具体的需要怎么做，做出来具体效果如何，会碰到什么样的困难我们无从所知，如此自由度这么高没有条条框框限制着，后面不出问题才怪！真正技术流的人物招不进来，反而竟是招些眼高手低爱吹牛皮的人，我们这是研发部，不是聊天室！这样的人员配备，不说别的像样的东西都做不出来几个。失望透了！ 5月份开始，把之前搁置的计划通通付诸实施，真的不能再拖了，能执行一点是一点。 &#160; 生活： 这周六结束，就开始八天的小长假咯。打算是前3-4天在家休息，后面两天时间去泉州和崇武逛逛，吃吃小吃看看海什么的，可是一看到这诡异的天气，顿时有担忧起后面的行程了，难道第n次一个人旅行又要面对着该死的天气？！ 过完小长假，首先得继续晚上的锻炼，这一个半月没有练感觉腹部又反弹了，肌肉还在可好像脂肪又有点增长的趋势。接着得把买的那好几本的书给通关，太久没看书总觉得自己缺点什么，没有知识的不断补充人似乎没底气起来。加班的时候还突然对吉他产生兴趣，看了些入门资料，不知道自己想培养的这个爱好能否继续下去，先看看入门书籍呗，等真决定买吉他了就必须逼自己把这个东西学好来。 哎，加班让我舍弃太多东西了，现在要一个个拾起，如果再有下次，我真的……不能忍！！！！]]></description>
			<content:encoded><![CDATA[<p><font color="#0000ff"><strong>工作：</strong></font></p>
<p> <img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://www.liurain.com/upload/2012/04/2012.4.29-1.jpg" />
<p style="text-indent: 2em">本周是心情跌到谷底的一周，来了做GIS的研究生，本以为有个搭档我能解绑不用那么累，可是天不遂人愿，研究生只待了一天就不干了。这样的临时变卦也不是没遇见过，可是发生在自己身上就特能真切的体会那种感受。这其实不算什么，本周的后面几天才让我对这个公司有了彻底的失望。来了个所谓的张副总，没先到比想象中的还糟糕，他聊聊天泡泡茶不知道一整天在工作什么，对这我真有点意见，可是看到周四他下发的五月份任务清单，我才觉得他泡茶聊天真没什么，至少不会对我们工作产生影响，属于无害。现在这样瞎指挥真的让我不能忍！原来从java调到去做.NET，然后又去做缺人的研究的GIS，我已经觉得自己已经忍让到极限，现在有点眉目了竟然5月份让我去做与GIS一点都没关系的内容，这不让我前面的努力付诸东流？不能知人善任是对整个部门很伤的一个东西！而且还有意思的是他分配了任务后只是跟我们说明了下做什么以及一些其他需求，而具体的需要怎么做，做出来具体效果如何，会碰到什么样的困难我们无从所知，如此自由度这么高没有条条框框限制着，后面不出问题才怪！真正技术流的人物招不进来，反而竟是招些眼高手低爱吹牛皮的人，我们这是研发部，不是聊天室！这样的人员配备，不说别的像样的东西都做不出来几个。失望透了！</p>
<p style="text-indent: 2em">5月份开始，把之前搁置的计划通通付诸实施，真的不能再拖了，能执行一点是一点。</p>
<p>&#160;</p>
<p><font color="#0000ff"><strong>生活：</strong></font></p>
<p> <img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://www.liurain.com/upload/2012/04/2012.4.29-2.jpg" />
<p style="text-indent: 2em">这周六结束，就开始八天的小长假咯。打算是前3-4天在家休息，后面两天时间去泉州和崇武逛逛，吃吃小吃看看海什么的，可是一看到这诡异的天气，顿时有担忧起后面的行程了，难道第n次一个人旅行又要面对着该死的天气？！</p>
<p style="text-indent: 2em">过完小长假，首先得继续晚上的锻炼，这一个半月没有练感觉腹部又反弹了，肌肉还在可好像脂肪又有点增长的趋势。接着得把买的那好几本的书给通关，太久没看书总觉得自己缺点什么，没有知识的不断补充人似乎没底气起来。加班的时候还突然对吉他产生兴趣，看了些入门资料，不知道自己想培养的这个爱好能否继续下去，先看看入门书籍呗，等真决定买吉他了就必须逼自己把这个东西学好来。</p>
<p style="text-indent: 2em">哎，加班让我舍弃太多东西了，现在要一个个拾起，如果再有下次，我真的……不能忍！！！！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liurain.com/?feed=rss2&#038;p=429</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C#深究：委托与事件 在.net的争霸战 ，你选择了谁？（异步委托产生的原因）</title>
		<link>http://www.liurain.com/?p=433</link>
		<comments>http://www.liurain.com/?p=433#comments</comments>
		<pubDate>Fri, 27 Apr 2012 07:05:00 +0000</pubDate>
		<dc:creator>雨狮</dc:creator>
				<category><![CDATA[学习天地]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[事件]]></category>
		<category><![CDATA[委托]]></category>

		<guid isPermaLink="false">http://www.liurain.com/?p=433</guid>
		<description><![CDATA[之前转载了两篇文章《C#深究：抛开书本谈 委托，为什么需要委托，它成就了什么？》、《C#深究：抛开书本，为什么出现了事件，事件与委托有什么渊源？》，对委托和事件有了一定的了解，下面该是将它们整合起来一起讨论的时候了，本文转载地址：IamBetter_Mr.W &#160; 如果你对下面8个问题,可以轻而易举的回答,那么这篇博文对你没什么作用. 1、为什么在发布者与订阅者的模式中，我们使用了事件而不使用委托变量？ 2、为什么我们通常的多播委托的返回类型都是void？ 3、如何让事件只允许一个方法注册？ 4、非void多播委托如何返回多个返回值？ 5、当委托链表的注册方法发生异常时，如何解决？ 6、如何解决事件中的委托方法的延时效果？ 7、实现异步委托……？ &#160; 理清思路： 委托 好比中介所，你在我这里注册了方法，我就代替你完成任务。 事件 好比微博，凡是收听我微博的人，只要我更新了微博(自己触发什么条件)，收听我的人就会知道我更新了，以便做出自己的动作(评论/转发)。即：事件必须自己触发。 &#160; 下面来解决疑问： 1、为什么在发布者与订阅者的模式中，我们使用了事件而不使用委托变量？ class Program &#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args) &#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Pub pub = new Pub(); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub sub = new Sub(); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += sub.OnDisplay; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.ChangeNumber(); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display(100); &#160;&#160;&#160;&#160;&#160;&#160;&#160; } &#160;&#160;&#160; } [...]]]></description>
			<content:encoded><![CDATA[<p>之前转载了两篇文章<a href="http://www.liurain.com/?p=424" target="_blank">《C#深究：抛开书本谈 委托，为什么需要委托，它成就了什么？》</a>、<a href="http://www.liurain.com/?p=427" target="_blank">《C#深究：抛开书本，为什么出现了事件，事件与委托有什么渊源？》</a>，对委托和事件有了一定的了解，下面该是将它们整合起来一起讨论的时候了，本文转载地址：<a href="http://www.cnblogs.com/IAmBetter/archive/2012/02/09/2344115.html" target="_blank">IamBetter_Mr.W</a></p>
<p>&#160;</p>
<p>如果你对下面8个问题,可以轻而易举的回答,那么这篇博文对你没什么作用.</p>
<p><strong>1、为什么在发布者与订阅者的模式中，我们使用了事件而不使用委托变量？</strong></p>
<p><strong>2、为什么我们通常的多播委托的返回类型都是void？</strong></p>
<p><strong>3、如何让事件只允许一个方法注册？</strong></p>
<p><strong>4、非void多播委托如何返回多个返回值？</strong></p>
<p><strong>5、当委托链表的注册方法发生异常时，如何解决？</strong></p>
<p><strong>6、如何解决事件中的委托方法的延时效果？</strong></p>
<p><strong>7、实现异步委托……？</strong></p>
<p>&#160;</p>
<p>理清思路：</p>
<p>委托 好比中介所，你在我这里注册了方法，我就代替你完成任务。</p>
<p>事件 好比微博，凡是收听我微博的人，只要我更新了微博(自己触发什么条件)，收听我的人就会知道我更新了，以便做出自己的动作(评论/转发)。即：事件必须自己触发。</p>
<p>&#160;</p>
<p>下面来解决疑问：</p>
<p><font color="#ff0000"><strong>1、为什么在发布者与订阅者的模式中，我们使用了事件而不使用委托变量？</strong></font></p>
<blockquote><p>class Program      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Pub pub = new Pub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub sub = new Sub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += sub.OnDisplay;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.ChangeNumber();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display(100);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; public delegate void DisplayEventHandle(int number);       <br />&#160;&#160;&#160; class Pub       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public DisplayEventHandle Display;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void ChangeNumber()      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; for (int i = 0; i &lt; 10; i++)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (i == 2)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (Display != null)//如果注册方法       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Display(i);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void OnDisplay(int i)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;The number is {0}&quot;,i);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>分析：(“=”是赋值操作，”+=”是注册方法)</p>
<p>对于使用委托变量，那么在类的内部 委托变量(字段)必须是Public，这样不安全。</p>
<p>pub.Display(100);事件本来就是需要调用ChangeNumber()方法当i=2的时候触发的，然后订阅者做出一系列的动作，但是现在pub.Display(100);委托自己就可以调用订阅者的动作，影响到了所有订阅者。</p>
<p>&#160;</p>
<p>修改代码：</p>
<blockquote><p>class Program      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Pub pub = new Pub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub sub = new Sub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += sub.OnDisplay;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.ChangeNumber();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //pub.Display(100); 报错</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; public delegate void DisplayEventHandle(int number);       <br />&#160;&#160;&#160; class Pub       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public event DisplayEventHandle Display;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void ChangeNumber()      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; for (int i = 0; i &lt; 10; i++)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (i == 2)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (Display != null)//如果注册方法       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Display(i);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void OnDisplay(int i)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;The number is {0}&quot;,i);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>分析：</p>
<p>对象再也无法直接调用委托变量了，因为加了event事件，本质是生成了私有private的委托。所以无法进行赋值操作，也不能直接调用。</p>
<p>这样给客户端少了一些使用类内部变量的权利。</p>
<p>&#160;</p>
<p><font color="#ff0000"><strong>2、为什么我们通常的多播委托的返回类型都是void？</strong></font></p>
<p>对于单播委托，咱们不讨论了，太简单了。</p>
<p>对于多播委托：</p>
<blockquote><p>委托变量+=方法1；</p>
<p>委托变量+=方法2；</p>
</blockquote>
<p>试想下，咱们都知道委托变量的声明，参数和返回类型都是和方法一样的，那么委托调用方法的时候，如果有返回值，这个返回值是方法1，还是方法2的。</p>
<p>比如：拿上面的微博案例来说，我是发布者，我可能今天心情不好，然后发布了一条微博，我根本不关心，谁收听我，也不关心收听者对我的评论。即：事件发布者，他运行了某个动作之后，如果这个动作内的条件满足，那么就触发 订阅者的动作。事件发布者根本不需要关心，你订阅者的返回值。</p>
<p>但是，你要说，我就是想知道返回值是多少？好，我们做个测试：</p>
<blockquote><p>class Program      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Pub pub = new Pub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub1 sub1 = new Sub1();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub2 sub2 = new Sub2();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += sub1.OnDisplay;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += sub2.OnDisplay;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.ChangeNumber();//I am Sub2</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; public delegate string DisplayEventHandle();       <br />&#160;&#160;&#160; class Pub       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public event DisplayEventHandle Display;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void ChangeNumber()      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; for (int i = 0; i &lt; 10; i++)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (i == 2)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (Display != null)//如果注册方法       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; string str=Display();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(str);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub1      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;I am Sub1&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub2      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;I am Sub2&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>答案是：最后一个订阅者的返回值。</p>
<p>&#160;</p>
<p><font color="#ff0000"><strong>3、如何让事件只允许一个方法注册？</strong></font></p>
<p>可能有时候，我们的微博只想让一个人收听，不想让前任女友收听，怎么办？</p>
<p>从技术层面分析：</p>
<p>1、我们订阅的时候如何追加订阅者？通过符号”+=“是吧，但是我们说过，”=“符号也可以委托定义，从这个角度着手，可不可以让事件变成不可访问的(private)，然后在内部利用”=”进行订阅，而不是让客户自己”+=“符号订阅。</p>
<blockquote><p>class Program      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Pub pub = new Pub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub1 sub1 = new Sub1();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub2 sub2 = new Sub2();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.AddDL(sub1.OnDisplay);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.AddDL(sub2.OnDisplay);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Speaking();</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; public delegate string DisplayEventHandle();       <br />&#160;&#160;&#160; class Pub       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; private event DisplayEventHandle Display;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void AddDL(DisplayEventHandle method)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Display = method;//这里是&quot;=&quot;不是&quot;+=&quot;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void RemoveDL(DisplayEventHandle method)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Display -= method;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void Speaking()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (Display != null)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; string str = Display();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(str);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub1      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;I am Sub1&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub2      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;I am Sub2&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>分析：有朋友可能会问，这样不是和刚才一样么？带返回值的委托变量。其实不是的，当你使用+=的时候，2个方法都会被加入委托链表，而使用”=“只是覆盖。</p>
<p>有点类似于属性，对，就是事件访问器。</p>
<p>如下代码：</p>
<blockquote><p>class Program      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Pub pub = new Pub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub1 sub1 = new Sub1();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub2 sub2 = new Sub2();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //pub.Display = sub1.OnDisplay;//错误，因为Display本质还是私有的委托，只是这里定义了2个委托       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += sub1.OnDisplay;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += sub2.OnDisplay;//覆盖sub1方法       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Speaking();</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; public delegate string DisplayEventHandle();       <br />&#160;&#160;&#160; class Pub       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; private DisplayEventHandle display;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public event DisplayEventHandle Display       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; add { display = value; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; remove { display -= value; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void Speaking()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (display != null)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; string str = display();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(str);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub1      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;I am Sub1&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub2      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;I am Sub2&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p><img src="http://www.liurain.com/upload/2012/04/2012.4.27-1.jpg" /></p>
<p>分析：</p>
<p>通过分析，发现事件的本质是 <font color="#ff0000"><strong>生成一个private的委托变量</strong></font>，这就是为什么无法通过 事件变量=方法 操作的原因，因为这个变量是委托的变量，无法访问。但是可以通过事件访问器访问，修改事件访问器可以限制方法进入 委托链表。</p>
<p>&#160;</p>
<p><font color="#ff0000"><strong>4、非void委托如何返回多个返回值?</strong></font></p>
<p>思路：</p>
<p>1、我们知道多播委托注册方法之后，会产生一个委托链表，那么我们可以把这个委托的注册方法遍历出来吗？</p>
<blockquote><p>public delegate string DL();      <br />&#160;&#160;&#160; class Program       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DL one = DoSomething;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one += Attacking;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //delegate[] dls; 这样是错误的，下面解释了       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Delegate[] dlArray =one.GetInvocationList();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; foreach(var n in dlArray)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(n.Method.Name);//遍历方法名字       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; static string DoSomething()      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;do it&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; static string Attacking()      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;Attack&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>首先，我们要先理清出一个概念：</p>
<p>delegate与Delegate有什么区别？</p>
<p>Delegate：是一个抽象基类，它引用静态方法或引用类实例及该类的实例方法。然而，只有系统和编译器可以显式地从Delegate类派生出委托类型。</p>
<p>MulticastDelegate：是一个继承于Delegate的类，其拥有一个带有链表格式的委托列表，该列表称为调用列表，在调用多路广播委托时，将按照调用列表中的委托出现的顺序来同步调用这些委托。平常我们声明一个delegate的类型，都是继承于MulticastDelegate类的(注意：不能显示的从此类进行派生。这点与Delegate类是一样的，只有系统和编译器可以显示的进行派生)。</p>
<p>delegate是一个C#关键字，用来定义一个行的委托类型(继承自MulticastDelegate类)。</p>
<p>&#160;</p>
<p>2、方法名遍历出来了，咱们利用List&lt;&gt;把每个方法的结果遍历出来</p>
<blockquote><p>public delegate string DL();      <br />&#160;&#160;&#160; class Program       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DL one = DoSomething;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one += Attacking;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //delegate[] dls; 这样是错误的，下面解释了       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Delegate[] dlArray =one.GetInvocationList();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; List&lt;string&gt; lists = new List&lt;string&gt;();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; foreach(var n in dlArray)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(n.Method.Name);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DL newone = (DL)n;//把Delegate显示转换成DL类型，因为DL类的基类是Delegate类       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; string str = newone();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; lists.Add(str);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; foreach (var n in lists)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(n);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static string DoSomething()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;do it&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; static string Attacking()      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;Attack&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>应用于事件中：</p>
<blockquote><p>class Program      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Pub pub = new Pub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub1 sub1 = new Sub1();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub2 sub2 = new Sub2();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display +=new DisplayEventHandle(sub1.OnDisplay);//注册方法       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += new DisplayEventHandle(sub2.OnDisplay);//注册方法</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; List&lt;string&gt; lists=pub.Doing();//事件由发布者的某个条件触发      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; foreach (var n in lists)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(n);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; public delegate string DisplayEventHandle();</p>
<p>&#160;&#160;&#160; class Pub&#160; //发布者      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public event DisplayEventHandle Display;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; List&lt;string&gt; lists = new List&lt;string&gt;();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Delegate[] dls;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public List&lt;string&gt; Doing()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (Display != null)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; dls = Display.GetInvocationList();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; foreach (var n in dls)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(n.Method.Name);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DisplayEventHandle one=(DisplayEventHandle)n;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; string str = one();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; lists.Add(str);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return lists;      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160; <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub1//订阅者      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;I am Sub1&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; class Sub2       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;I am Sub2&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />}</p>
</blockquote>
<p>事实上，发布者根本不关心这些订阅者返回什么，它关心的是订阅者注册的方法是否正确，是否会报错，影响发布者的方法执行和后面订阅者方法的执行，所以这种技术主要用于返回订阅者方法的异常处理信息。</p>
<p>&#160;</p>
<p><font color="#ff0000"><strong>5、当委托链表的注册方法异常时，如何解决？</strong></font></p>
<p>源代码：</p>
<blockquote><p>class Program      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Pub pub = new Pub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub1 sub1 = new Sub1();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub2 sub2 = new Sub2();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += new DisplayEventHandle(sub1.OnDisplay);//注册方法       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += new DisplayEventHandle(sub2.OnDisplay);//注册方法</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Doing();//事件由发布者的某个条件触发      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; public delegate string DisplayEventHandle(object sender, EventArgs e);</p>
<p>&#160;&#160;&#160; class Pub&#160; //发布者      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public event DisplayEventHandle Display;       <br />&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void Doing()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (Display != null)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Display(this,EventArgs.Empty);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub1//订阅者      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay(object sender, EventArgs e)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;I am Sub1&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; class Sub2       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay(object sender, EventArgs e)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;I am Sub2&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>思考：如果订阅者方法异常了怎么办？对，我们利用try catch调试。</p>
<p>修改代码：</p>
<blockquote><p>public void Doing()      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (Display != null)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; try       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; string str=Display(this, EventArgs.Empty);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(str);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; catch (Exception e)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(e.Message.ToString());       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>class Sub1//订阅者      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay(object sender, EventArgs e)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //return &quot;I am Sub1&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; throw new Exception(&quot;sub1方法异常了&quot;);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>如果Sub1方法出了异常的话，那么就会终止对Sub2方法的调用，虽然Doing()可以执行下去了。但是影响了其他订阅者。</p>
<p>从这个层面思考，我们把注册的方法按照上面提到过的遍历一下，就能解决，因为在Foreach循环内当一个方法出了问题，只影响到问题方法本身。</p>
<blockquote><p>class Program      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Pub pub = new Pub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub1 sub1 = new Sub1();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub2 sub2 = new Sub2();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display +=new DisplayEventHandle(sub1.OnDisplay1);//注册方法       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += new DisplayEventHandle(sub2.OnDisplay2);//注册方法</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; List&lt;string&gt; lists=pub.Doing();//事件由发布者的某个条件触发      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; foreach (var n in lists)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(n);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; public delegate string DisplayEventHandle(object sender,EventArgs e);</p>
<p>&#160;&#160;&#160; class Pub&#160; //发布者      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public event DisplayEventHandle Display;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; List&lt;string&gt; lists = new List&lt;string&gt;();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Delegate[] dls;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public List&lt;string&gt; Doing()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (Display != null)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; dls = Display.GetInvocationList();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; foreach (var n in dls)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; try       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(n.Method.Name);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DisplayEventHandle one = (DisplayEventHandle)n;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; string str = one(this, EventArgs.Empty);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; lists.Add(str);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; catch (Exception e)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(e.Message.ToString());       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return lists;      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160; <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub1//订阅者      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay1(object sender,EventArgs e)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; throw new Exception(&quot;Sub1方法异常了&quot;);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; class Sub2       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay2(object sender, EventArgs e)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;I am Sub2&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>输出:</p>
<p>OnDisplay1</p>
<p>Sub1方法异常了</p>
<p>OnDisplay2</p>
<p>I am Sub2</p>
<p>总结：这样即知道了哪个方法异常了，又不影响其他订阅者调用自己的方法。</p>
<p>&#160;</p>
<p><font color="#ff0000"><strong>6、如何处理事件中的委托方法的超时？</strong></font></p>
<p>上面可知，订阅者的注册方法如果有问题，会导致异常，然后影响到发布者的Doing()方法，还有一种让发布者的Doing()方法经过很长时间执行的，就是超时。</p>
<p>但是超时不会影响发布者把订阅者感兴趣的信息发布给订阅者，也不影响发布者的正常执行，只是执行Doing()会很长时间而已。</p>
<p>&#160;</p>
<p>分析下：</p>
<p>1、发布者 执行某个动作的时候(事件由发布者自己触发)，根据订阅者感兴趣的信息会调用订阅者的注册方法（比如 当一个数字大于10的时候）。</p>
<p>2、我们按F11调试的时候都会发现，当触发事件的时候，就会转到订阅者的内部方法上去，也就是说，当前线程在执行订阅者的方法，所以Main函数内部的客户端就在等待方法执行完毕之后，才能继续下面的代码操作。</p>
<p>&#160;</p>
<p>这里有点深度的：我举个例子</p>
<p>当Main函数在执行一个发布者的方法的时候</p>
<p>比如 计算1-100的和，如果一个感兴趣的参数是和，当和大于10的时候，这个时候，线程就会转到订阅者的方法上去，这个时候，客户端(Main函数的方法还能执行吗？)显然不可用继续执行了，必须等待订阅者执行完，才能继续下面的计算操作。</p>
<blockquote><p>class Program      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Pub pub = new Pub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub1 sub1 = new Sub1();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub2 sub2 = new Sub2();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += new DisplayEventHandle(sub1.OnDisplay1);//注册方法       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += new DisplayEventHandle(sub2.OnDisplay2);//注册方法</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; List&lt;string&gt; lists=pub.Doing();//事件由发布者的某个条件触发      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; foreach (var n in lists)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(n);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;线程已经回到Main函数&quot;);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; public delegate string DisplayEventHandle(object sender,EventArgs e);</p>
<p>&#160;&#160;&#160; class Pub&#160; //发布者      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public event DisplayEventHandle Display;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; List&lt;string&gt; lists = new List&lt;string&gt;();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; Delegate[] dls;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public List&lt;string&gt; Doing()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (Display != null)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; dls = Display.GetInvocationList();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; foreach (var n in dls)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;现在是方法：&quot;+n.Method.Name);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DisplayEventHandle one = (DisplayEventHandle)n;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; string str = one(this, EventArgs.Empty);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; lists.Add(str);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return lists;      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160; <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub1//订阅者      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay1(object sender,EventArgs e)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Thread.Sleep(TimeSpan.FromSeconds(5));       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;线程已转到Sub1,等待5秒，Sub1方法执行&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; class Sub2       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public string OnDisplay2(object sender, EventArgs e)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &quot;线程已转到Sub2,Sub2方法执行。。。&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>输出：</p>
<p>现在是方法：OnDisplay1</p>
<p>现在是方法：OnDisplay2</p>
<p>线程已经转到Sub1，等待5秒，Sub1方法执行</p>
<p>线程已经转到Sub2，Sub2方法执行……</p>
<p>线程已经回到Main函数</p>
<p>&#160;</p>
<p>我们是发布者，我们需要的是立刻输出：线程已经回到Main函数，而订阅者的超时影响了我发布者的延迟输出。</p>
<p>还是拿微博来说：我是博主，我发微博就是抒发感情，和谁收听我，以及收听到我的信息没有以及如何对我做出反应都不关心。</p>
<p>但是现在，我必须等待订阅者方法结束了，我才可用操作，太让人生气了。</p>
<p>为了解决这个问题，怎么办？IL看结构：</p>
<p><img src="http://www.liurain.com/upload/2012/04/2012.4.27-2.jpg" /></p>
<p>分析：</p>
<p>1、事件的本质我们知道，是<strong>生成 一个private的委托变量</strong></p>
<p>2、委托的本质我们知道，是<strong>生成一个完整的继承与MulticastDelegate的类，委托本质是个类</strong></p>
<p>这个类里包括：</p>
<p>BeginInvoke()、EndInvoke()、Invoke()3个方法。</p>
<p>我们记得要调用委托方法的时候是这样操作的：</p>
<p>委托变量()；其实 实质就是 委托变量.Invoke();</p>
<p>对，就是这个方法是凶手，他妨碍了我们的发布者，让我们等待。</p>
<p>&#160;</p>
<p>KO它，开始 异步委托。</p>
<p>&#160;</p>
<p><font color="#ff0000"><strong>7、实现异步委托？</strong></font></p>
<p>异步就是一个主线程执行了(Main函数)，你要是委托调用方法，那是你的事情，你自己重新开辟新线程去搞，别影响我的主线程。</p>
<p>异步一般是Begin和End出现。</p>
<p>&#160;</p>
<p>1、BeginInvoke()执行时，从线程池抓取一个“没事干”的线程来替我去告诉订阅者调用委托方法。</p>
<p>注：对于调用BeginInvoke()方法的时候，让线程去调用委托方法，这个委托变量必须只能有一个方法被绑定，如果是多播委托，必须像上面那样GetInvocationList()获得所有委托对象，先遍历出所有委托对象，再使用BeginInvoke()方法。</p>
<p>2、Main()继续自己的线程执行下面的工作</p>
<p>3、EndInvoke()；当订阅者方法异常时，我们知道可以try catch捕获，但是只有在EndInvoke()才会抛出。(其实发布者并不关心这些抛出异常的信息)，并且抛出异常也是在另一个进程上。</p>
<p>&#160;</p>
<p>好了，开始写代码：</p>
<blockquote><p>class Program      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Pub pub = new Pub();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub1 sub1 = new Sub1();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Sub2 sub2 = new Sub2();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += new DisplayEventHandle(sub1.OnDisplay);//注册方法       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Display += new DisplayEventHandle(sub2.OnDisplay);//注册方法</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; pub.Doing();//事件由发布者的某个条件触发      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;线程还在Main()&quot;);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.ReadKey();//为什么这样写，因为主线程是Main函数，当他执行完之后，程序就结束了，可能子线程还没结束呢      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; public delegate void DisplayEventHandle(object sender, EventArgs e);</p>
<p>&#160;&#160;&#160; class Pub&#160; //发布者      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public event DisplayEventHandle Display;       <br />&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void Doing()       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (Display != null)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Delegate[] dels = Display.GetInvocationList();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; foreach (var n in dels)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DisplayEventHandle newone = (DisplayEventHandle)n;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; IAsyncResult result = newone.BeginInvoke(this, EventArgs.Empty, null, null);//新开辟一个线程       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //newone.EndInvoke(result);//加上这个效果如何？效果还是需要等待订阅者方法的结果，所以这个是没要添加的</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class Sub1//订阅者      <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void OnDisplay(object sender, EventArgs e)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Thread.Sleep(TimeSpan.FromSeconds(3));       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;Sub1线程&quot;);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; class Sub2       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void OnDisplay(object sender, EventArgs e)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;Sub2线程&quot;);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }       <br />}</p>
</blockquote>
<p>输出结果：</p>
<p>线程还在Main();</p>
<p>Sub2线程</p>
<p>Sub1线程</p>
<p>&#160;</p>
<p>总结：和我们预期效果一样，注意上面的Console.ReadKey(),不写这个，程序运行完成将导致子线程的输出无法完成。可能难以理解，分析下：</p>
<p>1、对于主线程就是Main()函数，对于子线程分为 前台线程和后台线程，我们这里的就是后台线程，对于后台线程，只要主线程运行结束，程序就结束了，不会管这些后台线程，但是对于前台线程注意了，必须前台线程结束了，主线程才会结束。</p>
<p>2、这里是 并行执行的，不要以为因为Foreach遍历就会先执行Sub1，其实是2个一起执行的。也就是说 后台线程最长利用了3秒钟。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liurain.com/?feed=rss2&#038;p=433</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C#深究：抛开书本，为什么出现了事件，事件与委托有什么渊源？</title>
		<link>http://www.liurain.com/?p=427</link>
		<comments>http://www.liurain.com/?p=427#comments</comments>
		<pubDate>Thu, 26 Apr 2012 13:08:00 +0000</pubDate>
		<dc:creator>雨狮</dc:creator>
				<category><![CDATA[学习天地]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[委托]]></category>

		<guid isPermaLink="false">http://www.liurain.com/?p=427</guid>
		<description><![CDATA[看了上篇的《抛开书本谈 委托，为什么需要委托，它成就了什么？》对委托有了基本的了解，还是重申一遍那句话：委托就是给方法定义类型。一般提到委托，都会很自然的联想到事件，那么事件和委托到底有怎样的渊源能？《抛开书本，为什么出现了事件，事件与委托有什么渊源？》会告诉你答案，转载地址：IAmBetter_Mr.W。 思路：委托—&#62;事件存在的价值—&#62;事件的进化—&#62;总结 &#160; 1、参照上一篇博文 代码如下，山寨版委托： public delegate void CYDL(string name); &#160;&#160;&#160;&#160;&#160; class Program &#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args) &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CYDL one = new CYDL(Dancing); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one += new CYDL(Singing); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; PersonCY(“Mr.w”,one); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void PersonCY(string name,CYDL one) &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one(name); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Dancing(string name) [...]]]></description>
			<content:encoded><![CDATA[<p>看了上篇的《抛开书本谈 委托，为什么需要委托，它成就了什么？》对委托有了基本的了解，还是重申一遍那句话：<font color="#ff0000"><strong>委托就是给方法定义类型</strong></font>。一般提到委托，都会很自然的联想到事件，那么事件和委托到底有怎样的渊源能？《抛开书本，为什么出现了事件，事件与委托有什么渊源？》会告诉你答案，转载地址：<a href="http://www.cnblogs.com/IAmBetter/archive/2012/02/08/2342800.html" target="_blank">IAmBetter_Mr.W</a>。</p>
<p>思路：委托—&gt;事件存在的价值—&gt;事件的进化—&gt;总结</p>
<p>&#160;</p>
<p>1、参照上一篇博文</p>
<p>代码如下，山寨版委托：</p>
<blockquote><p>public delegate void CYDL(string name);</p>
<p>&#160;&#160;&#160;&#160;&#160; class Program</p>
<p>&#160;&#160;&#160;&#160;&#160; {</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CYDL one = new CYDL(Dancing);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one += new CYDL(Singing);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; PersonCY(“Mr.w”,one);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void PersonCY(string name,CYDL one)</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one(name);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Dancing(string name)</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(“{0}会跳舞”,name);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Singing(string name)</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(“{0}会唱歌”,name);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160; }</p>
</blockquote>
<p>上面是一个简单的案例，也不是正规的委托：</p>
<p>正规版：</p>
<blockquote><p>public delegate void CYDL(string name);      <br />&#160;&#160;&#160; class Program       <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CYDL one = new CYDL(Dancing);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one += new CYDL(Singing);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one(&quot;Mr.w&quot;);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Dancing(string name)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;{0}会跳舞&quot;,name);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Singing(string name)       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;{0}会唱歌&quot;,name);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>思考一个问题：我们学习到现在，几乎很少在Main函数内部 从一个类内部调用这个类的另一个方法，是吧？这也太有损面向对象这个概念了。</p>
<p>现在我们把各个方法放进不同的类里，然后再利用委托调用</p>
<p>代码如下：</p>
<blockquote><p>public delegate void CYDL(string name);     <br />&#160;&#160;&#160; class Person      <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void PersonCY(string name, CYDL one)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one(name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }      <br />&#160;&#160;&#160; class Program      <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Person person = new Person();      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; person.PersonCY(&quot;Mr.w&quot;,Dancing);//这样直接代入方法也是可以的，编译器会自动委托类型      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Dancing(string name)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;{0}会跳舞&quot;, name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Singing(string name)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;{0}会唱歌&quot;, name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>&lt;注意&gt;</p>
<p>分析下：为什么person.PersonCY(“Mr.w”,Dancing);//这样直接代入方法也是可以的，编译器会自动委托类型？</p>
<p>利用IL指令查看：</p>
<p><img src="http://www.liurain.com/upload/2012/04/2012.4.26-1.jpg" /></p>
<p>1、发现ldftn指令把Dancing()方法在Load堆内的地址压入了堆载。</p>
<p>2、newobj发现这里新建CYDL委托实例</p>
<p>即：这里是隐式转换成委托类型的。</p>
<p>&#160;</p>
<p>好了，继续进入正题，</p>
<p>static void Main(string[] args)   <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Person person = new Person();    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CYDL one = Dancing;    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one += Singing;    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; person.PersonCY(&quot;Mr.w&quot;,one);    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>好了，这样就符合我们的一般的模式了，即：类的对象调用方法。</p>
<p>缺点：每当实例化一个对象，那么就有可能要改变委托变量的绑定方法，或者重新声明一个委托变量two，这样是不是太麻烦了。面向对象的有一个封装的概念，让我们把这个委托变量封装到类内部，让对象可以调用。</p>
<p>&#160;</p>
<p>进化1：</p>
<blockquote><p>public delegate void CYDL(string name);     <br />&#160;&#160;&#160; class Person      <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public CYDL one;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void PersonCY(string name, CYDL one)     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one(name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }      <br />&#160;&#160;&#160; class Program      <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Person person = new Person();      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; person.one = Dancing;      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; person.one += Singing;      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; person.PersonCY(&quot;Mr.w&quot;,person.one);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Dancing(string name)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;{0}会跳舞&quot;, name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Singing(string name)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;{0}会唱歌&quot;, name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>缺点：细心的朋友可能发现了，调用PersonCY()，重复代入了one的委托变量。</p>
<p>&#160;</p>
<p>进化2：</p>
<p>即：</p>
<blockquote><p>public delegate void CYDL(string name);     <br />&#160;&#160;&#160; class Person      <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public CYDL one;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void PersonCY(string name)     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (one != null)//判断委托是否绑定了方法      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one(name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }      <br />&#160;&#160;&#160; class Program      <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Person person = new Person();      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; person.one = Dancing;      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; person.one += Singing;      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; person.PersonCY(&quot;Mr.w&quot;);&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Dancing(string name)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;{0}会跳舞&quot;, name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Singing(string name)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;{0}会唱歌&quot;, name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>但是我们知道，对于字段来说，委托类型的变量也是字段，我们通常是在访问权限上是private私有的。问题来了，如果设置了委托变量为私有的访问权限，那么我们如何给委托绑定方法呢？(在其他非集成类中无法调用这个变量)</p>
<p>对于以往，我们对于字段的处理是使用属性，可是委托有没有类似于属性的东西？</p>
<p>&#160;</p>
<p>进化3：时间出场</p>
<p>如下：</p>
<blockquote><p>public delegate void CYDL(string name);     <br />&#160;&#160;&#160; class Person      <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public event CYDL one;//就这么简单，加个event</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void PersonCY(string name)     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (one != null)//判断委托是否绑定了方法      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; one(name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }      <br />&#160;&#160;&#160; class Program      <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Person person = new Person();      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //person.one = Dancing; 这里是赋值操作，会报错      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; person.one += Singing;      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; person.PersonCY(&quot;Mr.w&quot;);&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Dancing(string name)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;{0}会跳舞&quot;, name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Singing(string name)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;{0}会唱歌&quot;, name);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }</p>
</blockquote>
<p>event实质就是声明一个私有的委托，使得委托封装。</p>
<p>所以对于一个私有字段，person.one = Dancing；肯定会报错。</p>
<p>查看IL代码：</p>
<p><img src="http://www.liurain.com/upload/2012/04/2012.4.26-2.jpg" /></p>
<p>变量one:private class DL.CYDL说明自动生成了一个私有的变量。所以无法使用“=”赋值。</p>
<p>上图可以看出：一个委托会注册和注销方法，本质是在加载的时候加载了add_one和remove_one方法。</p>
<p>本质：委托就是一个类，当执行public delegate void CYDL(string name);的时候就会产生一个完整的类。</p>
<p>&#160;</p>
<p>以上就是简单的事件的概念，可能有朋友会问怎么和winform中的事件不一样啊？</p>
<p>进化4：像样的事件</p>
<p>事件有2个用户：被监视者、监视者，事件必须本身触发。</p>
<p>可能难以理解，我举个例子：</p>
<p>1、被监视者 如果发生某种改变，监视者 会根据这个改变做出相应的对策</p>
<p>2、那么监视者如何知道 被监视者改变了呢，这就是注册事件。</p>
<p>面向对象的设计有 继承关系、聚合关系、依赖关系，一般OBServer模式就是耦合度低的依赖关系。</p>
<p>&#160;</p>
<p>很形象的比如微博，我是博主，你们都订阅我，我发布新的微博信息了，你们就都收到了我的信息，然后对我的信息作出回应，如：转发，评论等。</p>
<blockquote><p> class 微博     <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public delegate void 委托();      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public event 委托 事情;      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; private int 数字;      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void 数到10()      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; for (int i = 1; i &lt; 100; i++)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 数字 = i;//当我在博客上数到10的时候，就告诉收听我的人</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (事情 != null)//判断是否有博友收听我的微博     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (数字 == 10)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 事情();//就触发收听我的人的方法      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class 博友1     <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void 转发()      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;我知道你数到10了，我抓发你的微博&quot;);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }      <br />&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; class 博友2     <br />&#160;&#160;&#160; {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; public void 评论()      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;我也知道你数到10了，我评论了你的微博&quot;);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160; }     <br />上面是服务端，如何触发呢？      <br />请看下列代码：      <br /> class Test      <br />&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main()      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 微博 博主 = new 微博();      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 博友1 one = new 博友1();      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 博友2 two = new 博友2();      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 博主.事情 +=new 微博.委托(one.转发);      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 博主.事情 += new 微博.委托(two.评论);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 博主.数到10();</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }     <br />&#160;&#160;&#160; }</p>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.liurain.com/?feed=rss2&#038;p=427</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

