<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_Sean's Code Garden!</title><subtitle type="text">Code's seed here, Arc's Tree grows up somewhere, and some day!</subtitle><id>http://feed.cnblogs.com/blog/u/33911/rss</id><updated>2012-03-01T14:28:44Z</updated><author><name>jujusharp</name><uri>http://www.cnblogs.com/jujusharp/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jujusharp/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/33911/rss"/><entry><id>http://www.cnblogs.com/jujusharp/archive/2012/02/02/async-controller-from-net-mvc-2-to-4.html</id><title type="text">异步控制器, 从ASP.NET MVC 2到4</title><summary type="text">在ASP.NET MVC 4即将到来之际, 我将尝试在本文中带领大家回顾异步控制器在.NET MVC中的历史变化, 本文主要通过实例代码演示这些变化, 并没有针对异步控制器使用的场合进行分析和讨论, 因此, 如果有同学对该何时使用异步控制器有疑问可能要失望了. 不过好在针对这块的讨论已经有很多文章了, 相信大家不难查到. 也希望大家能从微软在代码设计的变化中感受到异步操作和async/await的阵阵热风, 并且在未来更多的去了解相关内容</summary><published>2012-02-02T15:23:00Z</published><updated>2012-02-02T15:23:00Z</updated><author><name>jujusharp</name><uri>http://www.cnblogs.com/jujusharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jujusharp/archive/2012/02/02/async-controller-from-net-mvc-2-to-4.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jujusharp/archive/2012/02/02/async-controller-from-net-mvc-2-to-4.html"/><content type="html">&lt;div&gt;&lt;p&gt;&lt;strong&gt;前言&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这篇文章主要针对即将到来的ASP.NET MVC4中的异步控制器做一个回顾和展望, 并未涉及到讨论异步控制器的使用场合, 如果对异步控制器何时使用仍然纠结的同学, 这次可能会让你们失望了, 不过关于这方面的讨论和分析其实蛮多的, 大家也可以自行搜索.好了,废话少说,上正文.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;异步控制器&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在MS越来越提倡异步操作的时代, ASP.NET MVC中的异步操作却一直显得比较落伍, 对于开发人员来说, 实现一个异步控制器往往要比普通的控制器花费更多的代码. 这个特性是在ASP.NET MVC 2中被引入的, 之后就没怎么改过,直到现在, 随着C# 5和 async/await的即将到来, 异步控制器现在已经跟普通的控制器操作代码一样的简练啦. 现在(当然得等ASP.NET MVC4,.NET 4.5和C# 5正式的发布之后), 你可以写出下面这样简洁的代码啦:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; async Task&amp;lt;ViewResult&amp;gt; FooBar() &lt;br /&gt;{&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; View(await DoSomething(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Some Action&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;));&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;怎样? 真的是很简单的吧~~&lt;/p&gt;&lt;p&gt;展望固然重要, 不过在这之前, 也请大家随着我来回顾下一步控制器在ASP.NET MVC 2到4中的实现, 对比往往更能让人印象深刻.&lt;/p&gt;&lt;p&gt;注意:下面关于ASP.NET MVC 4的例子都是基于ASP.NET MVC Developer Preview. 在正式版中, 这种实现可能会有所变化.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;在ASP.NET MVC 2/3中的异步控制器&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在ASP.NET MVC 2/3 中, 要实现一个一步控制器,你将不得不实现两个方法, 一个叫XXXAsync, 另外一个叫XXXCompleted, 同时你的控制器还要改成继承自&lt;span style="font-family: Consolas, 'Courier New', Courier, monospace;"&gt;AsyncController,&amp;nbsp;&lt;/span&gt;关于这个的实现和讲解已经有很多现成的例子, 这里我就直接从&lt;a href="http://msdn.microsoft.com/zh-cn/library/ie/ee728598.aspx"&gt;MSDN&lt;/a&gt;上搬过来一个例子吧.&lt;/p&gt;&lt;p&gt;要看异步控制器, 我们首先看看同样功能的同步实现, 大家应该都很熟悉了:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; PortalController: Controller&lt;br /&gt; {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; ActionResult News(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; city)&lt;br /&gt;   {&lt;br /&gt;     NewsService newsService = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; NewsService();&lt;br /&gt;     ViewStringModel headlines =       newsService.GetHeadlines(city);&lt;br /&gt;     &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; View(headlines);&lt;br /&gt;    }&lt;br /&gt; }&lt;/div&gt;&lt;p&gt;我们再来看其异步实现方式:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; PortalController : AsyncController&lt;br /&gt; {&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; NewsAsync(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; city)&lt;br /&gt; {&lt;br /&gt; AsyncManager.OutstandingOperations.Increment();&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; newsService = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; NewsService();&lt;br /&gt; newsService.GetHeadlinesCompleted += (sender, e) =&amp;gt;&lt;br /&gt; {&lt;br /&gt; AsyncManager.Parameters[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;headlines&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;] = e.Value;&lt;br /&gt; AsyncManager.OutstandingOperations.Decrement();&lt;br /&gt; };&lt;br /&gt; newsService.GetHeadlinesAsync(city);&lt;br /&gt; }&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; ActionResult NewsCompleted(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] headlines)&lt;br /&gt; {&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; View(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;News&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ViewStringModel&lt;br /&gt; {&lt;br /&gt; NewsHeadlines = headlines&lt;br /&gt; });&lt;br /&gt; }&lt;br /&gt; } &lt;/div&gt;&lt;p&gt;&amp;nbsp; 看看上面的实现, 不得不承认, 相对同步控制器, 异步Action开发人员要做的工作还是要多一些的. 但在.NET4.0的大环境中, 我们也只能用这种方式来实现了.&lt;/p&gt;&lt;p&gt;&amp;nbsp; 当然, MSDN的例子是标准的分层的实现例子, 在这个例子中,你将不得不实现自己的Service层, 如果你只是想简单的调用异步Action, 有没有方便的办法呢? 答案是有的, 在.NET 4.0中,微软带来了Task类, 感兴趣的同学可以猛击&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.threading.tasks.task.aspx"&gt;这里&lt;/a&gt;. 有了Task,如果你只是想简单的一个函数里面做异步操作也是可以滴:&lt;span style="background-color: #ffffff; font-family: tahoma, arial, helvetica, sans-serif; font-size: small; line-height: normal;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; PortalController : AsyncController &lt;br /&gt;{&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; NewsAsync(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; city)&lt;br /&gt; {&lt;br /&gt; AsyncManager.OutstandingOperations.Increment();&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; task = Task.Factory.StartNew(() =&amp;gt; RunThread(city));&lt;br /&gt; task.ContinueWith(t =&amp;gt;&lt;br /&gt; {&lt;br /&gt; AsyncManager.Parameters[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;headlines&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;] = t.Result;&lt;br /&gt; AsyncManager.OutstandingOperations.Decrement();&lt;br /&gt; });&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; ActionResult NewsCompleted(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] headlines)&lt;br /&gt; {&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; View(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;News&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ViewStringModel&lt;br /&gt; {&lt;br /&gt; NewsHeadlines = headlines&lt;br /&gt; });&lt;br /&gt; }&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; RunThread(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; input)&lt;br /&gt; {&lt;br /&gt; Thread.Sleep(&lt;span style="color: #800080;"&gt;5000&lt;/span&gt;);&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; input;&lt;br /&gt; }&lt;br /&gt; }&lt;/div&gt;&lt;p&gt;当然, 代码并没有减少太多, 不过也算是一种不太复杂的实现, 虽然没那么好看, 但也不至于太难看.&lt;/p&gt;&lt;p&gt;&amp;nbsp; 下面我们再来看看ASP.NET MVC 4中的异步控制器吧.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;ASP.NET 4 Developer preview中的异步控制器&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在抛弃了对.NET 3的支持之后, ASP.NET MVC 4 彻底拥抱了Task类库, 你不需要再蛋疼的给每个Action写两个方法, 也无需傻傻的手动对异步Action计数器增减了(&lt;span style="font-family: Consolas, 'Courier New', Courier, monospace;"&gt;AsyncManager.OutstandingOperations.Increment()&lt;/span&gt;), 现在的你只需拿起手指, 轻轻敲几下, 其他的事情都由系统帮你完成.&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; PortalController : AsyncController &lt;br /&gt;{&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; Task&amp;lt;ViewResult&amp;gt; News( &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; city)  &lt;br /&gt; {&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; Task.Factory.StartNew(() =&amp;gt; RunThread(city))&lt;br /&gt; .ContinueWith(t =&amp;gt;&lt;br /&gt;  {&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; View(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ViewStringModel()&lt;br /&gt; {&lt;br /&gt; Text = t.Result&lt;br /&gt; });&lt;br /&gt; });&lt;br /&gt; }&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; RunThread(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; input)&lt;br /&gt; {&lt;br /&gt; Thread.Sleep(&lt;span style="color: #800080;"&gt;5000&lt;/span&gt;);&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; input;&lt;br /&gt; }&lt;br /&gt; } &lt;/div&gt;&lt;p&gt;&amp;nbsp; 是不是好多了?Lamda可以让一切更爽:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; Task&amp;lt;ViewResult&amp;gt; News(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; city) {&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; Task.Factory.StartNew(() =&amp;gt; RunThread(city))&lt;br /&gt; .ContinueWith(t =&amp;gt; View(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ViewStringModel{ Text = t.Result }));&lt;br /&gt; }&lt;/div&gt;&lt;p&gt;那么, 是不是到这里就要说再见了呢? 不是的, 请继续往下看.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;伟大的async/await&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;虽然还未到正式发布的时候, 不过如果我们跟着微软的目光往前更进一步, 在ASP.NET和C# 5中, 或者我们从&lt;a href="http://msdn.microsoft.com/en-us/vstudio/gg316360"&gt;这里&lt;/a&gt;可以给.NET 4增加Async 的功能, 在有了async和await这两个关键词之后, 异步编码就更简单啦, 这其中也包括异步控制器的相关操作:&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; PortalController : AsyncController {&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; async Task&amp;lt;ViewResult&amp;gt; News(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; city)&lt;br /&gt; {&lt;br /&gt; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; View(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ViewStringModel()&lt;br /&gt; {  &lt;br /&gt; Text = await NewThread(city)&lt;br /&gt; });&lt;br /&gt; }  &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; async Task&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&amp;gt; NewThread(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; input)  &lt;br /&gt; {  &lt;br /&gt; Thread.Sleep(&lt;span style="color: #800080;"&gt;5000&lt;/span&gt;);  &lt;br /&gt; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; input; &lt;br /&gt; }&lt;br /&gt; } &lt;/div&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;由于有了async和await关键字以及Task类库的帮助, 在可预见的未来里, 我们操作异步控制器就可以像操作普通的控制器一样了, 但就像其他的众多新增的.NET特性一样, 能力越大, 责任也就越大, 方便也往往意味着滥用. 异步控制器固然好, 但也并非每种场合都适合用它, 不恰当的使用它往往会导致服务器需要在不同的线程之间切换, 而这也带来了更多额外的开销. 在开发领域, 我们尤其要注意性能往往比其他任何东西都重要, 因此, 请在确实能提高性能和用户相应的情况下使用异步控制器.&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/jujusharp/aggbug/2320225.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jujusharp/archive/2012/02/02/async-controller-from-net-mvc-2-to-4.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jujusharp/archive/2011/12/31/why_this_expression_equals_10.html</id><title type="text">你知道为啥++[[]][+[]]+[+[]] = 10?</title><summary type="text">这篇文章是翻译自stackoverflow上的一个问题, 当然,是个蛋疼却有些意思的问题, ++[[]][+[]]+[+[]]结果是什么,你知道么? 看完文章我们会发现, 问题出现了不要紧, 最重要的其实是我们思考,分析和解决问题的方式, 如何在给定了一个难题利用自己学到的知识融会贯通的解决这个问题才是最重要的.也希望大家在新的一年更快的成长把!</summary><published>2011-12-31T11:41:00Z</published><updated>2011-12-31T11:41:00Z</updated><author><name>jujusharp</name><uri>http://www.cnblogs.com/jujusharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jujusharp/archive/2011/12/31/why_this_expression_equals_10.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jujusharp/archive/2011/12/31/why_this_expression_equals_10.html"/><content type="html">&lt;p&gt;&lt;strong&gt; 前言&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个世界总有那么些人喜欢较真,喜欢研究,这不, 在StackOverflow上,有人就很认真的提了这个问题,&amp;nbsp; 幸运的是, 程序员永远是这个世界上最乐于帮助别人的人群之一, 于是, 真有人很热情的blabla的解释了原因.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;想看源地址的可以去这里: &lt;a href="http://stackoverflow.com/questions/7202157/can-you-explain-why-10"&gt;http://stackoverflow.com/questions/7202157/can-you-explain-why-10&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;问题 &lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;code&gt;++[[]][+[]]+[+[]]&lt;/code&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;在js中, 如果我们这样给一个变量赋值,不难发现它确实能返回一个值,而且还是10, 另外你可以在&lt;a href="http://sla.ckers.org/forum/read.php?24,33349,33405"&gt;这里&lt;/a&gt;看到更多更多类似这样的测试结果.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;那么, 为什么会返回值呢?为什么又是10呢?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;原因 &lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;很多热心人士都给出了自己的解释, 这里我就不一一列举了, 我只翻译下最佳答案(他解释得最为详细).&lt;/p&gt;&amp;nbsp;1. 解决问题的最好的方式之一就是分解它, 然后分而治之, 这里也一样, 首先上述表达式可以分解为:&lt;ol&gt;     &lt;/ol&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;++[[]][+[]]&amp;nbsp;&lt;br /&gt;+&lt;br /&gt;[+[]]&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;div&gt;&lt;code&gt;  2. 在js中, 表达式&lt;/code&gt;&lt;code&gt;+[]===0的结果为真, 这其实跟js编译器的设计有关的, 由于Js是弱类型语言,因此在我们想对某个对象进行一个操作时,js引擎总是会尝试先将这个对象转换为符合指定操作的对象类型然后再执行操作,在这里+会把后面[]转换为0然后执行别的结果,那么,上面的表达式可以进一步简化为下面这样子:&lt;/code&gt;&lt;br/&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;++[[]][0]&lt;br /&gt;+&lt;br /&gt;[0]&lt;/div&gt;&lt;/div&gt;由于[[]][0]表示取得数组[[]]的第一个元素, 因此我们可以得到:&lt;code&gt;&lt;/code&gt;&lt;br/&gt;&lt;/div&gt;&lt;/code&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;&lt;p&gt;[[]][0]返回该数组的内部数组([]),然而, 如果我们直接说[[]][0]===[]却不对, 为了避免错误的表述, 这里我们不放先称这个内部数组为A. &lt;/p&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;&lt;p&gt;++[[]][0] == A+1, 因为在js中,++表示自增1.&lt;/p&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;&lt;p&gt;++[[]][0] === +(A+1), 或者从另方面说,前面的结果永远是一个数字(js中,进行+1并不一定能保证结果是数字,但++得到的结果却永远是数字)&lt;/p&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp; 3.&amp;nbsp; 让我们继续上面的步骤对表达式进一步简化, 这里我们把A替换为[],然后得到简化的结果:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;+([]+1)&lt;br /&gt;+&lt;br /&gt;[0]&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;在js中, 后面这个表达式的结果仍然为真: []+1 ==="1", 因为空数组转换为字符串等同于"", 根据这个特点,我们可以得到下面的结论:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;+([] +1) === +("" +1);&lt;/li&gt;&lt;li&gt;+([] +1) === +("1");&lt;/li&gt;&lt;li&gt;+([] +1) === 1.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;4. 于是, 表达式可以进一步简化为下面这个结果:&lt;/p&gt;&lt;p&gt;&amp;nbsp; 1&lt;br /&gt;&lt;/p&gt;&lt;div&gt;&amp;nbsp; +&lt;br /&gt;[0]&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;我们不难发现[0] =="0"的结果同样为真, 这又是为啥呢? 其实原因跟上面一样的, 执行+的操作的时候, js引擎发现[0]是一个包含一个元素0的数组,因此,它会先将这个数组转换为字符串, 这样才能执行+操作(数组能匹配tostring的方法,但默认没有转换为数字的方式), 因此[0]会将其内部的所有元素拼接为一个字符串"0".&lt;br /&gt;&lt;/p&gt;&lt;p&gt;5. 好了, 到了揭晓答案的时刻啦, 通过上面的层层抽丝剥茧, 我们最终发现, 那么一大堆东西其实最后就是这样滴(数字+字符串=字符串):&lt;/p&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;1&lt;br /&gt;+&lt;br /&gt;"0"&lt;br /&gt;===&amp;nbsp;"10"&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Bazinga!!!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;关于+[] &lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;问题到这里结束了么? 应该没有,因为不少同学可能仍然对上面的解释有些疑问, 那么下面我们来补充下"+[]"把&lt;/p&gt;&lt;p&gt;首先看看一元操作符"+"的说明:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;11.4.6 Unary + Operator&lt;/p&gt;&lt;p&gt;The unary + operator converts its operand to Number type.&lt;/p&gt;&lt;p&gt;The production UnaryExpression : + UnaryExpression is evaluated as follows:&lt;/p&gt;&lt;ol&gt;     &lt;li&gt;     &lt;p&gt;Let expr be the result of evaluating UnaryExpression.&lt;/p&gt;     &lt;/li&gt;     &lt;li&gt;     &lt;p&gt;Return ToNumber(GetValue(expr)).&lt;/p&gt;     &lt;/li&gt;&lt;/ol&gt;&lt;/blockquote&gt;&lt;/div&gt;ToNumber()的说明:&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;Object&lt;/p&gt;&lt;p&gt;Apply the following steps:&lt;/p&gt;&lt;ol&gt;     &lt;li&gt;     &lt;p&gt;Let primValue be ToPrimitive(input argument, hint String).&lt;/p&gt;     &lt;/li&gt;     &lt;li&gt;     &lt;p&gt;Return ToString(primValue).&lt;/p&gt;     &lt;/li&gt;&lt;/ol&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;ToPrimitive()&lt;/code&gt; 的说明:&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;Object&lt;/p&gt;&lt;p&gt;Return a default value for the Object. The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType. The behaviour of the [[DefaultValue]] internal method is defined by this specification for all native ECMAScript objects in 8.12.8.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;[[DefaultValue]]&lt;/code&gt; 的说明:&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;8.12.8 [[DefaultValue]] (hint)&lt;/p&gt;&lt;p&gt;When the [[DefaultValue]] internal method of O is called with hint String, the following steps are taken:&lt;/p&gt;&lt;ol&gt;     &lt;li&gt;     &lt;p&gt;Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".&lt;/p&gt;     &lt;/li&gt;     &lt;li&gt;     &lt;p&gt;If IsCallable(toString) is true then,&lt;/p&gt;     &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.&lt;/p&gt;&lt;p&gt;b. If str is a primitive value, return str.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;关于数组的&lt;code&gt;.toString方法的说明:&lt;/code&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;15.4.4.2 Array.prototype.toString ( )&lt;/p&gt;&lt;p&gt;When the toString method is called, the following steps are taken:&lt;/p&gt;&lt;ol&gt;     &lt;li&gt;     &lt;p&gt;Let array be the result of calling ToObject on the this value.&lt;/p&gt;     &lt;/li&gt;     &lt;li&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;     &lt;p&gt;Let func be the result of calling the [[Get]] internal method of array with argument "join".&lt;/p&gt;     &lt;/blockquote&gt;&lt;/li&gt;     &lt;li&gt;     &lt;p&gt;If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).&lt;/p&gt;     &lt;/li&gt;     &lt;li&gt;     &lt;p&gt;Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list.&lt;/p&gt;     &lt;/li&gt;&lt;/ol&gt;&lt;/blockquote&gt;&lt;/div&gt;根据上面一堆堆的blabla, 我们就可以得出结论啦:+[] 等于+"",因为 [].join() === "".&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;这里, 我们再次回到关于+的定义:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;11.4.6 Unary + Operator&lt;/p&gt;&lt;p&gt;The unary + operator converts its operand to Number type.&lt;/p&gt;&lt;p&gt;The production UnaryExpression : + UnaryExpression is evaluated as follows:&lt;/p&gt;&lt;ol&gt;     &lt;li&gt;     &lt;p&gt;Let expr be the result of evaluating UnaryExpression.&lt;/p&gt;     &lt;/li&gt;     &lt;li&gt;     &lt;p&gt;Return ToNumber(GetValue(expr)).&lt;/p&gt;     &lt;/li&gt;&lt;/ol&gt;&lt;/blockquote&gt;&lt;/div&gt;""的ToNumber方法可参照下面的解释:&lt;p&gt;&lt;/p&gt;&lt;div&gt;The MV of StringNumericLiteral ::: [empty] is 0.&lt;/div&gt;&lt;p&gt;因此呢, +"" === 0,&amp;nbsp; 从而, +[] ===0.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;附言&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在这个提供分享和数字化的世界, 我们每天可能看到和学习了很多很多东西, 然后学习是一回事, 真正能学以致用, 将其在工作中融会贯通却又是另外一回事. 我们学习的最终目的是解决问题和创造新的东西, 但怎么利用已有的知识去解决问题却需要我们不断总结和思考.&lt;/p&gt;&lt;p&gt;因此我这里翻译这篇文章也不是仅仅给大家一个乐子, 更期待的是希望你和我能在新的一年中更好的去学会如果利用已知的和已有的资源去解决暂时可能的难题.&lt;/p&gt;&lt;p&gt;因为工作原因,很久没写东西, 在这个岁末旦初的时机终于再次提笔, 虽然只是翻译, 但也算是对自己有所帮助吧, 希望也能给你带来一些帮助.&lt;/p&gt;&lt;p&gt;水平有限, 如果有翻译或者解释不对的地方,还请大家多多谅解, 有砖请轻拍哈~~&lt;/p&gt;&lt;p&gt;最后, 也祝愿园友元旦快乐,年终奖多多把! &lt;br /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/jujusharp/aggbug/2309050.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jujusharp/archive/2011/12/31/why_this_expression_equals_10.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jujusharp/archive/2011/08/30/I_Like_Win_Phone.html</id><title type="text">我为啥喜欢WinPhone</title><summary type="text">从观望到入手到现在的淡然, 使用WinPhone差不多也近半年了. 也算是对WinPhone有些自己的看法, 数次在CB那种口水遍布的地方看到各种否定-&gt;驳"XXX-&gt;驳"驳XXX我都是很淡定的, 萝卜青菜,各有所爱, 特别是面对一个基本颠覆了以往的手机用户体验的手机来说, 有反对的声音在所难免,不过今天在看到有园友在园子里对WP吐槽, 觉得这样看来貌似大家对WP的偏见挺深的,就写篇文章来说说我的看法吧, 使用时间, 开发时间时间都有限, 如有不足甚至是错误的地方,还请大家轻拍为好~~</summary><published>2011-08-30T15:34:00Z</published><updated>2011-08-30T15:34:00Z</updated><author><name>jujusharp</name><uri>http://www.cnblogs.com/jujusharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jujusharp/archive/2011/08/30/I_Like_Win_Phone.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jujusharp/archive/2011/08/30/I_Like_Win_Phone.html"/><content type="html">&lt;p&gt;&lt;span style="font-size: 13px;"&gt;从观望到入手到现在的淡然, 使用WinPhone差不多也近半年了. 也算是对WinPhone有些自己的看法, 数次在CB那种口水遍布的地方看到各种否定-&amp;gt;驳"XXX-&amp;gt;驳"驳XXX我都是很淡定的, 萝卜青菜,各有所爱, 特别是面对一个基本颠覆了以往的手机用户体验的手机来说, 有反对的声音在所难免,不过今天在看到有园友在园子里对WP吐槽(.NET的地盘啊~~), 觉得这样看来貌似大家对WP的偏见挺深的,就写篇文章来说说我的看法吧, 使用时间, 开发时间时间都有限, 如有不足甚至是错误的地方,还请大家轻拍为好~~&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: 16px;"&gt;用户篇&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;其实看网上目前大部分吐槽的都是WP的界面过于单调. 主界面就一个, 只能放些大块块, 程序列表也一个, 如果你应用太多,会觉得找起来很烦. 而且对于很多追求花式的用户来说, 堂堂一个系统居然就只有两个界面可以跳来跳去, 其他的地方就只有进入应用了, 未免太过单调, 因此, 在一些尝过鲜的用户看来, 这玩意儿太单调了. 跟Android动辄4,5个主程序界面滑来滑去完全不可相提并论. 这Metro用着真是嘴里淡出个鸟来, 没意思.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;我刚用的时候也觉得应用列表只能滑来滑去太过繁杂, 当时想如果应用多了这个该怎么办呢(尼玛怎么跟广告的情节这么像)? 又没搜索(Mango已经支持搜索了). 但在使用了一段时间之后, 发现这玩意儿完全就是没必要的担心(当然是就我的使用习惯来说). 实际上虽然我安装的应用很多, 但平时常用的却很少,虽然没有2/8原则那么夸张, 不过大部分常用的应用放在主界面完全够用, 根本就不用担心主界面Tile过多导致超长的问题, 而且在用习惯了之后,基本要用哪个应用,该滑多大力度才能到达应用的图标也是相当熟悉, 所以,你有没有这个问题, 我反正是没有这个纠结的.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;不支持应用级别的多任务(实际系统的应用一直都是支持的,比如播放音乐等等)这个设定在mango之前确实比较坑爹(这点微软心底应该都觉得被Apple摆了一刀吧), 微软当初的意图是为了保证内存CPU能够完全提供给用户当前的应用,从而使用户体验最好, 不过后面发现这个设定实在太坑爹.因此Mango之后这项设定做了很漂亮的修改, 因此, 如果你抱怨这个, 我想你大可以等等再说, 毕竟作为一家大企业, 愿意下定决心推到一款已经存在7年之久的系统(我也算是WinMobile老用户了)完全重新开始, 恐怕目前也只有微软这样的企业有这样的气魄的.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;至于方向键,翻页之类的, 我只能说, 在触摸屏时代, 这些设计早已过时, 对, 我说的不仅仅是方向键, 也包括翻页. 如果你有不同看法,大可以看看DZone, twitter, 校内等等的消息设定, 对实时信息流目前主流的处理是动态加载到当前的列表中, 而实时性不高或者需要详细内容翻页的设置则是使用目前基本所有触屏都通用的左右划拉来实现, 这点不论Android, IPhone还是其他任何一款触摸系统都是如此,很少有人去舍触屏的长而加两个很丑的分页按钮的(当然你硬是要在应用里面加又有谁敢阻挡你呢?).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;span style="font-size: 13px;"&gt;编程语言的问题, 说实话我都不觉得这是个问题, 为啥不支持Flex,Java? Google现在可就是因为Java郁闷着呢, 你还想让微软来趟这趟浑水, 而且坊间人士常说Java,C#本一家, 即使你想招徕潜在的Java开发者, 这点不是问题, 问题是他们是否愿意. 以目前C#和VB的开发者数量来说, 其实微软担心的并不是潜在的开发者数量, 而是真正愿意积极投入的开发者(现在观望者众多), 所以在这块微软确实做了很多功夫(包括且不仅包括面向IOS和Android的object-c和java对应WinPhone API白皮书). 另一方面, 拿数据说话, WinPhone的应用增长数量确实比IPhone要慢些, 不过相对Android要高,10年10月正式上线, 今年7月份突破25000, 这份答卷也算不错的了. 也许你会说, 应用数量神马的都是浮云, 我关心的是中文应用数量, 确实,目前中文应用数量相对仍然薄弱, 不过目前QQ, QQ浏览器, Baidu浏览器, 各种常用的软件基本Market上面都有了, 而且, 各位看官, 这可是在Market中文市场还没有正式宣布支持的情况下的数量啊(目前微软不支持大陆开发者注册和购买). 当然, 我这其实在找客观理由, 作为用户, 如果你觉得自己想用的工具不够, 现在确实还不到中国用户使用Win Phone的最佳时机(另一方面, 不知道你想到没有, 对用户不利,那么对你我这样的个体开发户呢).&lt;/span&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;另一方面, 跟Android和IOS不一样的地方是, 微软对待普通应用和游戏是不一样的, 它们早已通过应用列表和XBox游戏列表分开. 另一方面, WinPhone的联系人通过内置Live,FB,Twitter账号早已做到社交和手机真正的一体啦, 而国内的微博很早就可以通过和Live账号绑定的方式做到一体化, renren也在最近和微软达成的&lt;a target="_blank" href="http://www.bloomberg.com/news/2011-08-24/renren-microsoft-to-ally-on-messaging-social-networks-in-china.html?cmpid=yhoo"&gt;合作协议&lt;/a&gt;. 因此, 可以说, 微软的意图和设计理念其实很明显, 它是想像地铁指示牌那样清晰准确的让用户快速到达自己的目的地, 得到自己想要的信息, 我去应用列表找应用,去游戏列表玩游戏, 去联系人玩社交等等等等(不妨看看WinPhone的&lt;a href="http://v.youku.com/v_show/id_XMjEzOTk1Nzgw.html"&gt;广告&lt;/a&gt;,蛮有意思的). 而不是像Android和IOS那样的应用超市(或者说应用摆摊), 用户看到的琳琅满目的应用图标摆在界面上. 信息是有了, 但需要用户仔细挑选. 我并非在此贬低这两种其中的任何一种, 这个世界有包容的文化,&amp;nbsp; 也有包容的处事方式. IOS(Android很大程度上模仿了它, 但模仿得足够好)提供的是一个超市那样的窗口, 由用户按类别或者使用习惯摆好每个柜台, 然后使用的时候从相应的柜台查找就是, 而WinPhone的设计思路则是来自于地铁指示, 微软认为, 手机只是我们生活的一部分, 它的角色是提供信息, 交流信息, 而不是让我们被其所累, 因此它尝试以Metro这种方式来实现自己的设计理念. 哪种更好, 在于你更习惯或者更加认同哪种方式.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;span style="font-size: 13px;"&gt;还有就是WinPhone内置的Office系列, 虽然现今的很多应用都可以做到, 不过微软内置的这款Office我是相当喜欢, 无论缩放还是编辑(内置的手写确实很棒), 体验都相当不错, 这点相信其他的移动OS很难媲美的. 即使你只是简单记录下所闻所见所得, Note也比其他的很多应用都好, 它不仅支持书写, 还支持录音. 最后还能同步到服务器, 而这些都是系统内置的服务.你喜不喜欢, 我反正是很喜欢的!&lt;/span&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;当然, 作为一款年轻甚至找不到前辈设计理念借鉴的手机, WinPhone仍然有很多不足, 这点微软自己也承认, 因此你看到的每一次重大更新微软都会带来所谓成千上万的新特性, 其实很多早就应该在那里, 它只是来晚了而已. 不过不管怎么变,这种设计理念不会改变, 这是它的魂, 你来,你用, 然后你习惯了这种方式, 它很方便, 解放了你很多事情, 你不习惯, 也不奇怪, 就换一台别的系统手机而已, 不用带着什么深仇大恨一样, 仅仅是你不同意它的思维方式, 就这么简单.&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: 16px;"&gt;开发者篇&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;我为啥觉得WinPhone很棒, 其实一方面也是当年被微软骗上了.NET的贼船(玩笑). 另一方面,毕竟微软在开发圈也混了这么多年, 所以一个免费却强大的VSExpress,一个好用的模拟器(虽然还没到完美, 仍然有些奇怪的小问题), 这些都比Eclipse+ Android模拟器要好用得多(当然Eclipse死忠不这么看也很正常, 谁没个自己的编程习惯呢), IOS最终还是没买Mac, 只试过一小段时间的虚拟机Mac, 没权利评价, 不过XCode现在要收费了. 基本上普通的应用只要你有了设计思路, 加上一些.NET和XAML编程基础, 折腾个能跑的东西花不了多少时间 (至于执行效率, 那就是后话, 哪种平台都必然会有调优的问题), 不过得益于当年微软Silverlight和XNA多年的开发社区积累, 加上足够的API,和MSDN详尽细致的实例和文档说明, 因此, 大部分WinPhone开发人员学习曲线都比其他两个平台要小得多.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;至于今天园友吐槽的应用设计限制,我想是他没有理解或者亲身去体验过WinPhone开发所致, AppBar上面的图标大小都是一样的, 所有要求大小,高度神马的都是一样的,同样, 由于WinPhone主题只有黑和白,所以相应要求你的AppBar上面的Icon必须是白色或者黑色的的. 我想说, 如果你自己去做一个应用或者使用了应用, 你就会明白这个是必须的, 试想, 你见过你操作系统里面的右键菜单有各式各样的按钮菜单么, 你见过Mac下面那排图标大小不一样的么? 除了这些基本的按钮因为要保持一致所以有所要求外, 只要你能让你的用户觉得就应该那样或者这样操作,你怎么做都行, 不过因为有个体验一致的问题,所以微软才建议你根据Metro的设计思路来做应用, 但这并非强制(如系统建议如果是Panorama,微软通常建议你不要加AppBar,不过其实我们通常就这么干,而且还动态换来换去), 虽然系统是非黑即白, 不过你愿意折腾的话, 你想怎么花花绿绿都没人说你(用户抱怨另说). 而且为了省去开发制作图标的辛苦,所以微软还特定给开发人员定制了一套常用的图标(如导航, 电话,蓝牙等等).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;同样的道理,作为一款新系统, 微软的接口提供可谓相当的小气, 这点完全不能跟当年的WinMobile相提并论, 可以说,当年的Mobile, 除了内核不能改之外, 基本没有你不能改的东西. 所以自从HTC开了先河之后, 你可以在WinPhone论坛看到各种各样的皮肤制作工具, 各种各样的插件, 各种各样自由定制的应用. 再看看今天, Mango之前甚至连摄像头都不能调用, 现在都没办法调用就是电话接听钩子(微软说是为了安全, 那就UAC下嘛, 经过用户许可也不可以么?), 所以导致到现在WinPhone都没办法做到挂靠来电事件然后获取来电号码的功能, 甚至来通话历史列表都拿不到, 其他的更别多说了, 还有访问存储卡这都不可以. 不过我们总算看到微软一直慢慢开放, 比如现在拿所有的联系人列表, 日程表等看似敏感的信息终于是可以了,还有今天园友吐槽的设置WIFI网络的问题, 实际现在只需要一个接口调用,就可以直接在应用内设置网路连接方式啦, 这点还算不错, 现在也有了可以早就应该有的后台服务和后台音乐播放功能了, 可以说现在用户基本的服务, 微软提供的接口都能做到. 相信微软不是傻子, 如何在用户隐私和丰富的功能接口提供之间权衡, 他们会很快掌握的.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;最后,一句话, 如果你并非大的工作室，现在切入这个平台是值得的, 园子里的朋友相信大部分都熟悉C#, 你不妨去试试装个SDK, 我这里说上千言万语都比不上你动下手亲自体验一把, 哪怕你现在手头没有实体机都毫无关系, 我相信你会很快爱上在它上面开发的(后面的痛苦开发过程我可不负责, IT人,痛苦是其宿命).&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: 16px;"&gt;总结&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;任何一款操作系统, 总有人爱有人恨, 其实挺正常的, 不过手机这玩意只是个工具, 我们犯不着提升到咬牙切齿的地步, 不喜欢, 换了就是. 想想如果这世界清一色都是IOS和Android那种思路的IOS系统(现今Android的那套换肤其实当年黑莓和WinMobile早就玩烂了, 架子和灵魂都是一样的), 我们的行事思维也太固化了. 有这么一个与众不同的手机操作系统存在, 至少也让你,你的朋友和家人有更多的选择, 不是么?&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;span style="font-size: 13px;"&gt;其实看系统好坏和看人是一样的, 切忌先入为主, 带着看前人的角度去看新人. 想想如果你对某人说, 张三那么帅,它的耳朵是那样的, 为啥你不是这样的. 要知道耳朵是身体的一部分, 必须和整个身体协调才能算美. 系统也一样.&lt;/span&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;PS:我非MS死忠,现在工作语言也是PHP,WinPhone也只是纯业余爱好而已，所以请勿给我乱贴标签。&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/jujusharp/aggbug/2160185.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jujusharp/archive/2011/08/30/I_Like_Win_Phone.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jujusharp/archive/2011/08/09/Windows-Phone-Developing-Summary-July.html</id><title type="text">WinPhone开发阶段总结</title><summary type="text">首先,这篇文章基本没什么技术含量,它主要是我对最近业余时间的WinPhone开发工作的一个总结.而且以我以往的学习经验来说，这篇文章很可能对读者中的大部分人都毫无用处，因为所谓学习方法因人而异,这我深有体会,所以这里我贴出自己关于WinPhone开发工作的一个阶段性总结只是希望里面哪怕能有一点点对你有所启示,那应该就算这篇文章的最大成功了.</summary><published>2011-08-08T17:13:00Z</published><updated>2011-08-08T17:13:00Z</updated><author><name>jujusharp</name><uri>http://www.cnblogs.com/jujusharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jujusharp/archive/2011/08/09/Windows-Phone-Developing-Summary-July.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jujusharp/archive/2011/08/09/Windows-Phone-Developing-Summary-July.html"/><content type="html">&lt;p&gt;首先,这篇文章基本没什么技术含量,它主要是我对最近业余时间的WinPhone开发工作的一个总结.而且以我以往的学习经验来说，这篇文章很可能对读者中的大部分人都毫无用处，因为所谓学习方法因人而异,这我深有体会,所以这里我贴出自己关于WinPhone开发工作的一个阶段性总结只是希望里面哪怕能有一点点对你有所启示,那应该就算这篇文章的最大成功了.&lt;br /&gt;&lt;br /&gt;自从去年工作方向由.NET转向PHP之后,C#基本就只能算我的一个业余爱好了,虽然仍然关注着这个圈子,也喜欢着这门语言,不过毕竟不是工作,没有实践,自己实在是感觉写不出怎样深刻的东西来,不过好在有了微软的WinPhone,纠结了几个月之后终于还是下手了HD7,也开始了自己WinPhone开发者的纯业余生活.到现在,虽然做的东西仍然很简单,但终于有了看得见的东西出来,我的手机号码归属地应用和中国地铁应用总算是成功挂到Market上了, 因此想想还是对这个阶段的开发工作做个总结比较好, 希望能给大家以参考.&lt;br /&gt;&lt;br /&gt;额,好像我总是如此啰嗦,还是上正文吧.&lt;br /&gt;&lt;br /&gt;1.写一行代码胜于看十页书.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 可能是因为之前已经有一定WPF/SL的经验,因此开发WinPhone应用时,除了微软官方的UI交互指南(因为WinPhone的UI设计理念确实和以前的应用不一样),我并未看一页书.大部分问题都是在遇到的时候才去网上查找资料解决的,当然,这并非说我没有查阅任何资料,实际上,直到现在,我每天仍然都会在WindowsPhoneGeek,MSDN和博客园上逛逛,看到不错的文章或者代码也会动手实践下.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 因此,以我的感受来说,对大部分的有一定的C#开发经验的园友来说,其实WinPhone的应用开发都不会太有难度以至于完全无法动手(当然,如果你做的是超级复杂的东西就另说啦),而且我始终认为从实际写代码中遇到问题-&amp;gt;解决问题的过程所收获的经验要比从书本中别人讲解的经验要深刻得多.如果你真的对WinPhone开发有兴趣,那么从现在开始就动手吧,不用纠结于去看哪本书,就我从目前介绍WinPhone开发的书本目录介绍来看,这些书本一定都是第一章和第二章都是毫无意义的(第一章介绍WinPhone的设计理念,第二章介绍VS的WinPhone开发环境部署,对很多人来说,很是浪费纸张).动手不仅能更快发现你应用中存在的设计问题,还能解决实际运行中你永远无法想到的意外.&lt;br /&gt;&amp;nbsp;&amp;nbsp; 当然,我并非反对看书,我的建议是如果你真想学WinPhone开发,那就多动手吧,这样你能更快进去开发的过程.&lt;br /&gt;&lt;br /&gt;2.不要一开始就想把应用的功能做得够大够强够完美.&lt;br /&gt;&amp;nbsp;&amp;nbsp; 不要一开始就想着做一个超级复杂,让人能一看就过目不忘的完美应用,这个我在开发过程中确实深有体会.其实我一开始并非想做上面的归属地应用和地铁路线图应用,而是一个斗地主的游戏,并且由于那时候WinPhone还不支持Socket,因此我一开始就计划设计一个足够聪明的AI系统,还为此复习了下很早之前丢掉的AI书籍,但越做下去发现越没信心做好,挫败感也越强.于是在经历了一个星期的空手而归之后,我开始进行反思,发现自己的AI知识实在是太过贫乏,这也不是我的优势所在,而且我的目的是至少前面一个应用是用来练手的,现在所做的工作实在不像,于是在下周开始果断放弃之前的工作,而该从手机归属地应用开始,一个界面简单,而是够实用.这样决定之后后面的工作就顺利了,并且有了第一个实用的工具第二个的思路也有了.这样在经历了一个多月的工作之后,终于还是将两个应用提交了,虽然知道所做仍然还是很浅薄,但看到能有东西挂在market上面的那种感觉确实完全不一样的.&lt;br /&gt;&lt;br /&gt;3. 做出应用的特色, 但不一定要复杂.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 好的应用不一定要非常强大,老实说, 归属地应用确实简单,就一个界面,四个按钮,其他没啥了.但我从Nokia3230到Samsung i900再到现在的HD7,我一直都认为这个功能是我们日常生活中一个不可缺的功能.而且有了核心的功能你就可以围绕它做更多的文章了.这样做到后面也许你会发现你一开始很简单的一个东西到后面可能会越来越强大.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 反之,如果一开始想太多,各种扩展,各种架构,那你反而可能一直在徘徊, 在浪费时间,结果到头来一无是处.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所以,如果你有了想法,并觉得这个想法确实会对别人的使用有很不错的帮助,那就开始动手吧,哪怕它实现起来并无太大技术含量.&lt;br /&gt;&lt;br /&gt;4. MVVM? 框架?&lt;br /&gt;&amp;nbsp;&amp;nbsp; 是否使用MVVM框架?这个问题我觉得因人而异,但你更应该看哪种方式你更顺手,我其实蛮喜欢SL的INotifyPropertyChanged,我甚至想要是C# 5中能实现属性自动双向绑定的特性(比如在要双向绑定的属性上加个特性[Bind(Ways.DoubleWay)])那C#该有多好哦.不过我对Command确实不太感冒(~~明显是因为境界不够),因此在实现时我保留了ViewModels,但对于事件还是用自己习惯的Click方式来实现,虽然这让MainPage.cs里的代码看起来太多太乱,不过现阶段来看这更有利于我书写代码的效率,同时修改代码我也更加习惯.因此我的建议是在初期你应该将很快提交能很好工作的应用这个目标放在首位,至于框架,以你自己习惯的方式来进行吧.哪种更有效则更适合你.&lt;br /&gt;&amp;nbsp;&amp;nbsp; 当然,上面的话也并非说我们可以一直这样,每个人都会在阶段性的工作之后对之前的代码进行总结,MVVM确实是SL/WPF一个不错的代码架构方式,同时它在单元测试时也更优异.因此,在总结的时候,你需要对之前的工作做一个权衡,而不是不经思考,一成不变的用最初的思考方式进行下去.&lt;br /&gt;&lt;br /&gt;5. 从实例开始&lt;br /&gt;&amp;nbsp;&amp;nbsp; 如果纠结于如何开始编写应用的话,那我建议你不妨从这里(http://create.msdn.com/en-US/education/catalog/)下一个示例代码开始.绝对不要小瞧这些实例代码的,我已经看到Market上面N多人直接把各种实例代码(比如BlackJack)改改就放上去了.这些代码不仅能给你一个比较标准的代码结构,而且能迅速带你进入正常的应用运行流程,这种过程我觉得比你在枯燥的书本上看一章要好得多.你可以看看GameStateManagementSample这样的例子,里面的架子基本上都已经帮你搭好了,菜单有了,主界面有了,唯一缺失的TODO就是player和enemy,这些只需要你按照自己设想的去填充就好了.微软别的不说,在对开发人员的引导方面,确实是做得不错的.&lt;br /&gt;&lt;br /&gt;6. 给用户提供做够多的反馈通道&lt;br /&gt;&amp;nbsp;&amp;nbsp; 可能你的应用开始的功能非常简单,但你要相信用户,很多你看不到的东西,他们都能看到和想到,因为用户不像你,你只有一个脑袋,但他们则是千千万万个聪明的脑袋,他们可能遇到你没遇到过的问题,这些都是用户反馈的好处,所以,一定记得在你的应用里面留下至少一个反馈的通道.我的第一个应用并没有留下自己的email链接进行反馈,因此看到的大部分反馈都是来自于review里面的.于是从中国地铁开始,我在关于页面中留下自己的邮箱,并提供了很方便的邮件编写链接.这之后我收到了两个很不错的反馈建议(如果他们有看到,我在这里谢谢所有提供反馈的WinPhoner).虽然最近因为工作的关系没办法马上发布新版本,不过我会尽快提交.&lt;br /&gt;&lt;br /&gt;7. 不要一开始就考虑赚钱&lt;br /&gt;&amp;nbsp;&amp;nbsp; 如果你一开始时抱着赚钱的想法来做Win Phone开发的话,那我想你很可能会有两个结果,一是因为失望而热情丧失并最终离开,二是因为需要纠结于怎样才能做出别人愿意花钱的应用而一事无成.当然,你也可能会成功,但对个人开发者来说,我建议大家一开始不要抱有太高期望值,你就把做应用当成一件结交朋友,锻炼能力的事情就够了.看到应用的发布,看到别人给你应用不错的评价,看到能给别人带来实打实的帮助,那种愉悦感也是相当不错的,至少能在以后的生活中给予你自己更多的信心,我个人认为这些东西有时候比那点点钱来得更快.&lt;br /&gt;&lt;br /&gt;8. 保护好你自己的核心代码&lt;br /&gt;&amp;nbsp;&amp;nbsp; 老实说,微软在代码保护上做得并不好,虽然没用过,但我曾在论坛上看到已经有人做出工具可以直接下载XAP文件,也看到很多win phone论坛放出了各种付费应用的破解文件.对.net应用来说,得到了XAP文件,如果你一点保护没做,基本就是赤裸裸的了,因此,虽然你永远无法防住那些真正想要偷窃你代码的无德份子,但一些基本的工作你还是得做,特别是如果你的应用基本没有需要与服务器交互的功能的时候. 当然,如果你的大部分核心逻辑都放在服务端这个问题就不用太担心了.&lt;br /&gt;&amp;nbsp;&amp;nbsp; 虽然如此,大家也不必太看重劳动果实偷窃这种事情,这样的人毕竟是少数.所以虽然很不幸,我的两个应用的优势都是本地数据存储, 我一开始有担心自己的劳动成果会被偷走(貌似也确实怀疑有人偷走过,当然我没有证据),也因此降低过热情,但想开了就淡定了.应用这玩意,本来自己的就是免费的,别人要偷也卖不了钱,那就偷去吧.这里我给大家的建议也是如此,你一定要做好最坏的打算,接受它但也不要放弃希望,这世界总有些事我们无法阻挡,但我们还能阻挡大部分的事情,不是么?&lt;br /&gt;&lt;br /&gt;好像我其实本来还有更多的体会,没有记东西的习惯,以后记起来再加上吧.下面写些工作总结吧.&lt;br /&gt;1. 生成代码时不要不设置项目的Netual Language,也不要设置成中文,至少目前不要这样设置,不然你在提交应用的时候会得到完全摸不着头脑的错误提示.如下图:&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/30356/2011080908521177.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;2. Paint.NET是个好工具,http://www.iconfinder.com/是个不错的图标网站&lt;br /&gt;&amp;nbsp;&amp;nbsp; 作为一个程序员,UI设计是个相当大的烦恼,这直接导致我对游戏类应用只能想想,无法动手.不过在设计图标的时候,Paint.NET确实很有帮助,虽然它没有PS那么强大,但对图层之间的操作还是相当方便的,所以我的两个应用的图标基本是先从iconfinder或者网上上面找个相关的图标,然后进行一些文字插入和混合,最终虽然图标仍然不好看,但总算有个东西了.所以你如果没有个设计老婆或者合伙人的话,那么你可以考虑使用下上面的工具凑活凑活吧.下面我给大家展示我自己的拙作(实在毫无艺术细胞,见笑了):&lt;/p&gt;&lt;p&gt;&lt;img style="float: left;" src="http://pic002.cnblogs.com/images/2011/30356/2011080901020016.png" /&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/30356/2011080901012989.png" alt="" height="63" width="63" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 上面就是我这差不多一个多月的业余工作总结,总体来说,离开.NET有一年多了,这次因为WinPhone而回归. 总体来说, WinPhone对个人开发者来说(工作室我没搞过,没资格谈论),如果你一开始野心并不是太大,从一开始一个小却有用的思路做起,那么这个生态环境其实也蛮适合你的.不需要太多的书籍(很多书籍也都是些重复的初级内容,没什么价值,甚至有些还不如MSDN或者Windows Phone Developer Tools Documentation), 只要你愿意,从现在动手,那么说不定有一天你真能收获意外之喜哦.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 总结下来目前能记起来的东西就这么多,忘掉的太多,技术方面的东西基本没有(有机会的话我会在后面把自己代码中认为稍稍拿得出手的东西跑出来给大家参考下),更多的是自己的一些工作思路的总结,希望能对你们有一点点帮助就行,如果能做到抛砖引玉那就更好啦!&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然后是广告时间啦, 呵呵,两个很简单的应用(Chinese Phone Address Finder/ Chinese Subway),首先,当然是得到你们更多的反馈了, 应用里面有邮箱地址,你们随时可以发邮件给我反馈, 还有就是, 俺最大的愿望就是能攒到明年的年费99刀, 你们要在用这两个应用实在很闲,可以考虑多点几下上面的广告哦,多谢啦,当然,不奢望,大家随意就行! 另外, 我在慢慢熟悉这个环境之后,也会努力做出更多希望能对大家有所帮助的工具来.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;再然后就是给大家一些信息,那就是虽然普及度无法和其他平台相比,但国内的Win Phone用户也是有一定数量的,我的归属地应用发布差不多20天左右,已经有了2k+的下载量(虽然到后期增长很缓慢), 相信那些热门的应用下载量应该会更大, 这多少算个不错的消息.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;最后唏嘘下, 从了解园子到现在差不多应该有4-5年了吧(真记不清了)看到园子里的活跃园友每年都不一样,心里总有些感叹.这个圈子陪了我挺多年的,一直都是当看客,没处理,心中确实有愧.真心希望各位园友都能从这里得到成长,成熟.&lt;/p&gt;&lt;img src="http://www.cnblogs.com/jujusharp/aggbug/2131642.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jujusharp/archive/2011/08/09/Windows-Phone-Developing-Summary-July.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jujusharp/archive/2011/08/04/C-Sharp-And-Closure.html</id><title type="text">C#与闭包</title><summary type="text">其实这篇文章早就放在脑子中了,只是一直没时间整理好,正好今天早上看到了园友提到,于是决定趁着晚上睡觉前还是整理下,然后写出来给大家分享分享,也希望能对大家有所帮助。C#的闭包，相对于java和其他静态语言，算是相当强悍和优雅的一个特性了，因此这篇文章和其他谈论闭包必谈js的文章不同，这篇文章主要从语法和IL的角度来给大家解释C#中闭包的定义，规范以及原理。</summary><published>2011-08-04T14:35:00Z</published><updated>2011-08-04T14:35:00Z</updated><author><name>jujusharp</name><uri>http://www.cnblogs.com/jujusharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jujusharp/archive/2011/08/04/C-Sharp-And-Closure.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jujusharp/archive/2011/08/04/C-Sharp-And-Closure.html"/><content type="html">&lt;p&gt;首先想说明一点,虽然有这样那样的不好的心态(比如中文技术书),但总体来说,国内的技术人员还是喜欢分享和教导别人的,这点我的个人感受和之前在园子里看到的朋友的感受恰恰相反.个人认为其实国内很多技术网友都是很热心的,可能因为语言问题同一个技术热点会稍稍落后国外一些,但一些成熟的或者基础的概念都可以找到很细致的中文介绍,特别是关于闭包,因为它的字面解释确实很绕,所以基本所有试图解释这一名词的同学都是尽量用自己认为最通俗易懂的方式来进行讲解.闲话扯远了,这里我就用C#语言来给大家解释下闭包吧.&lt;br /&gt;&lt;br /&gt;其实要提到闭包,我们还得先提下变量作用域和变量的生命周期.&lt;br /&gt;在C#里面,变量作用域有三种,一种是属于类的,我们常称之为field,第二种则属于函数的,我们通常称之为局部变量,还有一种,其实也是属于函数的,不过它的作用范围更小,它只属于函数局部的代码片段,这种同样称之为局部变量.这三种变量的生命周期基本都可以用一句话来说明,每个变量都属于它所寄存的对象,即变量随着其寄存对象生而生和消亡.对应三种作用域我们可以这样说,类里面的变量是随着类的实例化而生,同时伴随着类对象的资源回收而消亡(当然这里不包括非实例化的static和const对象).而函数(或代码片段)的变量也随着函数(或代码片段)调用开始而生,伴随函数(或代码片段)调用结束而自动由GC释放，它内部变量生命周期满足先进后出的特性。&lt;br /&gt;&lt;br /&gt;那么这里有没有例外呢?&lt;br /&gt;答案是有的,不过在提这点之前,我还需要给各位另外一个名词.都说c#就是MS版本的java,这话在.net 1.0可能可以这么说,但自2.0之后C#就可以自豪的说它绝非java了,这里面委托有很大的功劳,如果用过java和C#的人并且尝试过写winform程序时全部手写实现代码的人就会有这样一个感受,同样的click事件,在java中必须要无端的套个匿名类,但在c#中,你是可以直接将函数名+=到事件之后而不需要显示写上匿名委托的对象类型的,因为编译器会帮你做这部分工作,在3.0和以后的版本之中,微软将委托的用法更是发挥的淋漓精致,无论是简洁的Lamda还是通俗易懂的LINQ,都是源自委托的.&lt;br /&gt;&lt;br /&gt;你可能要问,委托和我们今天要讲的闭包又有什么关系呢?&lt;br /&gt;我们知道,c#,java和javascript,ruby,python这些语言不同,在c#和java的世界里面,原子对象就是类(当然还有struct和基本变量),而不是很多动态语言中的函数,我们可以实例化一个类,实例化一个变量,但不可以直接new 一个函数.也就是表面上看,我们是没办法像js那样将函数进行实例化和传递的.这也是为什么直到Java 7闭包才被姗姗来迟的加入java特性中。但对C#来说这些只是表象,我刚学c#的时候,看到最多的解释委托的话就是:委托啊,就相当于c++里面的函数指针啦.这句话虽然笼统,但确实有一定道理,通过委托特别是匿名委托这层对象的包装,我们就可以突破无法将函数当做对象传递的限制了.&lt;br /&gt;&lt;br /&gt;好像这里还是没讲到闭包和委托的关系,好吧,我太啰嗦了,下面从概念开始讲.&lt;br /&gt;闭包其实就是使用的变量已经脱离其作用域,却由于和作用域存在上下文关系,从而可以在当前环境中继续使用其上文环境中所定义的一种函数对象.&lt;br /&gt;好拗口,程序员,还是用示例来说明更好理解.&lt;br /&gt;首先来个最简单的javascript中常常见到的关于闭包的例子:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;    function f1(){&lt;br/&gt;var n=999;&lt;br/&gt;return function(){&lt;br/&gt;alert(n); // 999&lt;br/&gt;            return n;&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;    var a =f1();&lt;br/&gt;    alert(a());&lt;br/&gt;&lt;/div&gt;&lt;p&gt;这段代码翻译成C#代码就是这样：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public class TCloser&lt;br/&gt;    {&lt;br/&gt;        public Func&amp;lt;int&amp;gt; T1()&lt;br/&gt;        {&lt;br/&gt;            var n = 999;&lt;br/&gt;            return () =&amp;gt;&lt;br/&gt;            {&lt;br/&gt;                Console.WriteLine(n);&lt;br/&gt;                return n;&lt;br/&gt;            };&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;   &lt;br/&gt;    class Program{&lt;br/&gt;        static void Main(){&lt;br/&gt;            var a =new TCloser();&lt;br/&gt;            var b = a.T1();&lt;br/&gt;            Console.WriteLine(b());&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 从上面的代码我们不难看到,变量n实际上是属于函数T1的局部变量，它本来生命周期应该是伴随着函数T1的调用结束而被释放掉的，但这里我们却在返回的委托b中仍然能调用它，这里正是闭包所展示出来的威力，因为T1调用返回的匿名委托的代码片段中我们用到了n,而在编译器看来，这些都是合法的，因为返回的委托b和函数T1存在上下文关系，也就是说匿名委托b是允许使用它所在的函数或者类里面的局部变量的，于是编译器通过一系列动作(具体动作我们后面再说)使b中调用的函数T1的局部变量自动闭合，从而使该局部变量满足新的作用范围。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 因此如果你看到.net中的闭包，你就可以像js中那样理解它，由于返回的匿名函数对象是在函数T1中生成的，因此相当于它是属于T1的一个属性。如果你把T1的对象级别往上提升一个层次就很好理解了，这里就相当于T1是一个类，而返回的匿名对象则是T1的一个属性，对属性而言，它可以调用它所寄存的对象T1的任何其他属性或者方法，包括T1寄存的对象TCloser内部的其他属性。如果这个匿名函数会被返回给其他对象调用，那么编译器会自动将匿名函数所用到的方法T1中的局部变量的生命周转期自动提升并与匿名函数的生命周期相同，这样就称之为闭合。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 也许你会说，这个返回的委托包含的变量n只是编译器通过某种方式隐藏的对这个委托对象的一个同样对象的赋值吧，那么我们再对比下面两个方法：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public class TCloser{&lt;br/&gt;public Func&amp;lt;int&amp;gt; T1()&lt;br/&gt;    {&lt;br/&gt;        var n = 999;&lt;br/&gt;        Func&amp;lt;int&amp;gt; result = () =&amp;gt;&lt;br/&gt;        {&lt;br/&gt;            return n;&lt;br/&gt;        };&lt;br/&gt;&lt;br/&gt;        n = 10;&lt;br/&gt;        return result;&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    public dynamic T2()&lt;br/&gt;    {&lt;br/&gt;        var n = 999;&lt;br/&gt;        dynamic result =new { A = n };&lt;br/&gt;        n = 10;&lt;br/&gt;        return result;&lt;br/&gt;    }&lt;br/&gt;    static void Main(){&lt;br/&gt;        var a = new TCloser();&lt;br/&gt;        var b = a.T1();&lt;br/&gt;        var c = a.T2();&lt;br/&gt;        Console.WriteLine(b());&lt;br/&gt;        Console.WriteLine(c.A);&lt;br/&gt;    }&lt;br/&gt;} &lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最后输出结果是什么呢？答案是10和999，因为闭包的特性，这里匿名函数中所使用的变量就是实际T1中的变量，与之相反的是，匿名对象result里面的A只是初始化时被赋予了变量n的值，它并不是n，所以后面n改变之后A并未随之而改变。这正是闭包的魔力所在。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 你可能会好奇.net本身并不支持函数对象，那么这样的特性又是从何而来呢？答案是编译器，我们一看IL代码便会明白了。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 首先我给出c#代码：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public class TCloser {&lt;br/&gt;        public Func&amp;lt;int&amp;gt; T1(){&lt;br/&gt;            var n = 10;&lt;br/&gt;            return () =&amp;gt;&lt;br/&gt;            {&lt;br/&gt;                return n;&lt;br/&gt;            };&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public Func&amp;lt;int&amp;gt; T4(){&lt;br/&gt;            return () =&amp;gt;&lt;br/&gt;            {&lt;br/&gt;                var n = 10;&lt;br/&gt;                return n;&lt;br/&gt;            };&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这两个返回的匿名函数的唯一区别就是返回的委托中变量n的作用域不一样而已，T1中变量n是属于T1的，而在T4中，n则是属于匿名函数本身的。但我们看看IL代码就会发现这里面的大不同了：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;.method public hidebysig instance class [mscorlib]System.Func`1&amp;lt;int32&amp;gt; T1() cil managed{&lt;br/&gt;    .maxstack 3&lt;br/&gt;    .locals init (&lt;br/&gt;        [0] class ConsoleApplication1.TCloser/&amp;lt;&amp;gt;c__DisplayClass1 CS$&amp;lt;&amp;gt;8__locals2,&lt;br/&gt;        [1] class [mscorlib]System.Func`1&amp;lt;int32&amp;gt; CS$1$0000)&lt;br/&gt;    L_0000: newobj instance void ConsoleApplication1.TCloser/&amp;lt;&amp;gt;c__DisplayClass1::.ctor()&lt;br/&gt;    L_0005: stloc.0&lt;br/&gt;    L_0006: nop&lt;br/&gt;    L_0007: ldloc.0&lt;br/&gt;    L_0008: ldc.i4.s 10&lt;br/&gt;    L_000a: stfld int32 ConsoleApplication1.TCloser/&amp;lt;&amp;gt;c__DisplayClass1::n&lt;br/&gt;    L_000f: ldloc.0&lt;br/&gt;    L_0010: ldftn instance int32 ConsoleApplication1.TCloser/&amp;lt;&amp;gt;c__DisplayClass1::&amp;lt;T1&amp;gt;b__0()&lt;br/&gt;    L_0016: newobj instance void [mscorlib]System.Func`1&amp;lt;int32&amp;gt;::.ctor(object, native int)&lt;br/&gt;    L_001b: stloc.1&lt;br/&gt;    L_001c: br.s L_001e&lt;br/&gt;    L_001e: ldloc.1&lt;br/&gt;    L_001f: ret&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;.method public hidebysig instance class [mscorlib]System.Func`1&amp;lt;int32&amp;gt; T4() cil managed&lt;br/&gt;{&lt;br/&gt;    .maxstack 3&lt;br/&gt;    .locals init (&lt;br/&gt;        [0] class [mscorlib]System.Func`1&amp;lt;int32&amp;gt; CS$1$0000)&lt;br/&gt;    L_0000: nop&lt;br/&gt;    L_0001: ldsfld class [mscorlib]System.Func`1&amp;lt;int32&amp;gt; ConsoleApplication1.TCloser::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate4&lt;br/&gt;    L_0006: brtrue.s L_001b&lt;br/&gt;    L_0008: ldnull&lt;br/&gt;    L_0009: ldftn int32 ConsoleApplication1.TCloser::&amp;lt;T4&amp;gt;b__3()&lt;br/&gt;    L_000f: newobj instance void [mscorlib]System.Func`1&amp;lt;int32&amp;gt;::.ctor(object, native int)&lt;br/&gt;    L_0014: stsfld class [mscorlib]System.Func`1&amp;lt;int32&amp;gt; ConsoleApplication1.TCloser::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate4&lt;br/&gt;    L_0019: br.s L_001b&lt;br/&gt;    L_001b: ldsfld class [mscorlib]System.Func`1&amp;lt;int32&amp;gt; ConsoleApplication1.TCloser::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate4&lt;br/&gt;    L_0020: stloc.0&lt;br/&gt;    L_0021: br.s L_0023&lt;br/&gt;    L_0023: ldloc.0&lt;br/&gt;    L_0024: ret&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;看IL代码你就会很容易发现其中究竟了，在T1中，函数对返回的匿名委托构造的是一个类，名称为newobj instance void ConsoleApplication1.TCloser/&amp;lt;&amp;gt;c__DisplayClass1::.ctor()，而在T4中，则是仍然是一个普通的Func委托，只不过级别变为类级别了而已。&lt;br /&gt;那我们接着看看T1中声明的类c__DisplayClass1是何方神圣：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;.class auto ansi sealed nested private beforefieldinit &amp;lt;&amp;gt;c__DisplayClass1&lt;br/&gt;    extends [mscorlib]System.Object{&lt;br/&gt;    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()&lt;br/&gt;    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed{}&lt;br/&gt;    .method public hidebysig instance int32 &amp;lt;T1&amp;gt;b__0() cil managed{}&lt;br/&gt;    .field public int32 n&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;看到这里想必你已经明白了,在C#中,原来闭包只是编译器玩的花招而已,它仍然没有脱离.NET对象生命周期的规则，它将需要修改作用域的变量直接封装到返回的类中变成类的一个属性n,从而保证了变量的生命周期不会随函数T1调用结束而结束，因为变量n在这里已经成了返回的类的一个属性了。&lt;br /&gt;&lt;br /&gt;看到这里我想大家应该大体上了解C#闭包的来龙去脉了吧，C#中，闭包其实和类中其他属性、方法是一样的，它们的原则都是下一层可以畅快的调用上一层定义的各种设定，但上一层则不具备访问下一层设定的能力。即类中方法里的变量可以自由访问类中的所有属性和方法，而闭包又可以访问它的上一层即方法中的各种设定。但类不可以访问方法的局部变量，同理，方法也不可以访问其内部定义的匿名函数所定义的局部变量。&lt;br /&gt;&lt;br /&gt;这正是C#中的闭包，它通过超越java语言的委托打下了闭包的第一步基础，随后又通过各种语法糖和编译器来实现如今在.NET世界全面开花的Lamda和LINQ.也使得我们能够编写出更加简洁优雅的代码。&lt;br /&gt;&lt;br /&gt;附：后面是吐槽，与上文无关，大家可以略过，这篇文章其实两年之前在给同事讲C#闭包的时候就有想法整理出来和大家分享了，不过因为生活，工作，或许主要还是自己太懒的原因而拖着没动笔，到今天早上看到园友抱怨国内教书育人的氛围才最终决定利用晚上时间把它整理，然后放出来。我个人认为国内技术圈子的氛围尚可，虽然仍然很多浮躁和易怒在圈子里徘徊。但我们想想国内IT人的生存空间就容易理解了。每天最理想的情况朝9晚6的干活，晚上加班，周末加班这些都是常事，而对我们而言，只要想写出一些经过细细思考的东西都至少需要2个小时以上，而且最好中间不要有人来打扰，这也就注定我们在白天工作时候很难完全有时间静下来组织语言，刨掉这些时间，留给我们自己的生活时间又有多少呢？所以我每次看到有园友发表帖子的时间是晚上1点，2点甚至更晚，都毫不意外，&lt;br /&gt;我们并非专业写手，也不像国外IT人那样有充足的闲暇时光可以钻研自己的最爱，我们赚着他们的零头，买着比他们本子价格更贵的笔记本，担着比他们更高房价的压力来生活，这样的生活条件下我们这些可爱的社区(不仅限于cnblogs,javaeye,phpchina等)Geek们仍然如此活跃和热情，你还能抱怨什么呢？你要知道你看到的每篇文章(如果是工作人士的话)都是他们晚上从9点写到12点的生活点滴啊。&lt;br /&gt;&lt;br /&gt;所以，以后不要抱怨国内IT氛围吧,相对这个社会其他各行各业的浮躁，我觉得我们的IT圈子已经是很乐于分享的一个群体了。而且除了因为&amp;ldquo;天下武功,源自欧美,滞后于英语国家&amp;rdquo;的缘故，我们有些技术确实要晚些才能跟上国外社区的脚步，但对于一些基础知识的解释，已经有很多中文的文章解释得很不错了。像我以前在理解闭包的时候, javaeye上看到的一大堆，像WIKI,像阮一峰的文章，我个人认为对中文用户是足够了。当然，这只是我个人的观点，大家不必较劲。&lt;br /&gt;&lt;br /&gt;最后一点抱怨就是国内大大小小的抄袭网站,我想这也是影响我们中文用户查询资料的一个重要因素吧。以前曾经尝试过在baidu,google上搜索自己的文章，但结果相当令人失望,那些抄袭的网站从来都不在乎内容，因为这些可以通过抄来解决，而且不必带原文链接，不必表明作者。好像东西就是他们自己的一样，他们唯一在乎的就是SEO。这也导致我在使用google搜索的时候时常看到同一篇文章出现在某一页的所有搜索结果中，当然，网址是千奇百怪，实在让人无奈。有些网站即使标明了出处和作者，但用心略有险恶的不是给的链接，而是文字。而且,在这些抄袭者中,最让我感到悲哀的是大名鼎鼎的败毒文库,我至少看到不下5篇败毒文库里的文章是来自JE或者CSDN的,但在文库里面只有个文档，你看不到任何作者提示或者原文链接,也许有人会说，这也可能是作者自己上传的呀,但我个人认为这种可能性太小了,以国内IT人的风格,对败毒即使谈不上厌恶,也很少有主动去巴巴的，试想，一个国内最大的互联网公司都不尊重IT人的劳动(但愿我是错的吧),你又能对其他人说什么呢? 同样看看国外，就我看到的DZone, WindowsPhoneGeek等,每个都是很明确的给出原文的链接，基本上我很少看到有引用别人文章不给原文链接的文章的。而正是这些不尊重作者劳动的网站对国内互联网资料搜索造成大量的垃圾信息。&lt;br /&gt;&lt;br /&gt;引用：&lt;br /&gt;维基百科 &lt;a target="_blank" href="http://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_%28%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6%29"&gt;http://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_%28%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6%29&lt;/a&gt;&lt;br /&gt;博客园 &lt;a target="_blank" href="http://www.cnblogs.com/frankfang/archive/2011/08/03/2125663.html"&gt;http://www.cnblogs.com/frankfang/archive/2011/08/03/2125663.html&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/jujusharp/aggbug/2127999.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jujusharp/archive/2011/08/04/C-Sharp-And-Closure.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jujusharp/archive/2010/03/09/concurrent-collections-in-c-4.html</id><title type="text">.NET 4.0新增命名空间：System.Collections.Concurrent</title><summary type="text">集合类的需求总是源源不断，因此，不管是1.0到2.0的泛型，还是3.0到4.0的并行，.NET每个版本总会伴随着一些集合类的增长。由于并行计算现在已经越来越流行，这里我将对.NET 4.0中新增的命名空间System.Collections.Concurrent和它下面的类做一些简单的介绍。</summary><published>2010-03-08T16:35:00Z</published><updated>2010-03-08T16:35:00Z</updated><author><name>jujusharp</name><uri>http://www.cnblogs.com/jujusharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jujusharp/archive/2010/03/09/concurrent-collections-in-c-4.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jujusharp/archive/2010/03/09/concurrent-collections-in-c-4.html"/><content type="text">集合类的需求总是源源不断，因此，不管是1.0到2.0的泛型，还是3.0到4.0的并行，.NET每个版本总会伴随着一些集合类的增长。由于并行计算现在已经越来越流行，这里我将对.NET 4.0中新增的命名空间System.Collections.Concurrent和它下面的类做一些简单的介绍。</content></entry><entry><id>http://www.cnblogs.com/jujusharp/archive/2010/03/07/common-mistakes-in-php.html</id><title type="text">.NET程序员学PHP:常见编程错误</title><summary type="text">对入门的新手而言，我们很难完全避免犯错，但我们应该避免犯同样的错误，因此，总结对程序员来说是非常重要的一件事情。这里我总结和搜集了一些在PHP编程中可能大家会碰到的错误。希望能让我们在以后的开发过程中尽量避免。</summary><published>2010-03-07T07:21:00Z</published><updated>2010-03-07T07:21:00Z</updated><author><name>jujusharp</name><uri>http://www.cnblogs.com/jujusharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jujusharp/archive/2010/03/07/common-mistakes-in-php.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jujusharp/archive/2010/03/07/common-mistakes-in-php.html"/><content type="text">对入门的新手而言，我们很难完全避免犯错，但我们应该避免犯同样的错误，因此，总结对程序员来说是非常重要的一件事情。这里我总结和搜集了一些在PHP编程中可能大家会碰到的错误。希望能让我们在以后的开发过程中尽量避免。</content></entry><entry><id>http://www.cnblogs.com/jujusharp/archive/2010/03/04/static-in-php-and-c.html</id><title type="text">.NET程序员学PHP:static关键字</title><summary type="text">学习PHP也有一段时间了，PHP给我带来了很多不一样的视角，因此有些东西觉得还是需要总结一些，这里我们将重点分析下static关键字在C#和PHP中的不一样的地方和它在PHP中的使用。</summary><published>2010-03-03T16:42:00Z</published><updated>2010-03-03T16:42:00Z</updated><author><name>jujusharp</name><uri>http://www.cnblogs.com/jujusharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jujusharp/archive/2010/03/04/static-in-php-and-c.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jujusharp/archive/2010/03/04/static-in-php-and-c.html"/><content type="text">学习PHP也有一段时间了，PHP给我带来了很多不一样的视角，因此有些东西觉得还是需要总结一些，这里我们将重点分析下static关键字在C#和PHP中的不一样的地方和它在PHP中的使用。</content></entry><entry><id>http://www.cnblogs.com/jujusharp/archive/2010/03/02/use-full-path-instead-of-file-name-in-PHP.html</id><title type="text">PHP:使用'./include.php'替换'include.php’</title><summary type="text">在使用PHP进行开发时，我们常常使用函数require_once和include进行外部文件引用，然而有些小小的细节我们可能不太注意，这里作者将针对include函数进行一些简单的讲解。</summary><published>2010-03-02T12:45:00Z</published><updated>2010-03-02T12:45:00Z</updated><author><name>jujusharp</name><uri>http://www.cnblogs.com/jujusharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jujusharp/archive/2010/03/02/use-full-path-instead-of-file-name-in-PHP.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jujusharp/archive/2010/03/02/use-full-path-instead-of-file-name-in-PHP.html"/><content type="text">在使用PHP进行开发时，我们常常使用函数require_once和include进行外部文件引用，然而有些小小的细节我们可能不太注意，这里作者将针对include函数进行一些简单的讲解。</content></entry><entry><id>http://www.cnblogs.com/jujusharp/archive/2010/03/01/C-sharp-develope-tip-2.html</id><title type="text">C# Tips-2</title><summary type="text">在日常开发中，我们常常会有些经验或技巧需要总结，这里我给出自己在开发中进行的一些总结，希望对读者有所帮助</summary><published>2010-03-01T15:20:00Z</published><updated>2010-03-01T15:20:00Z</updated><author><name>jujusharp</name><uri>http://www.cnblogs.com/jujusharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jujusharp/archive/2010/03/01/C-sharp-develope-tip-2.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jujusharp/archive/2010/03/01/C-sharp-develope-tip-2.html"/><content type="text">在日常开发中，我们常常会有些经验或技巧需要总结，这里我给出自己在开发中进行的一些总结，希望对读者有所帮助</content></entry></feed>
