<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>收藏 on bystander&#39;s blog</title>
    <link>http://blog.leaver.me/tags/%E6%94%B6%E8%97%8F/</link>
    <description>Recent content in 收藏 on bystander&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Sat, 26 Apr 2014 16:36:28 +0000</lastBuildDate>
    <atom:link href="http://blog.leaver.me/tags/%E6%94%B6%E8%97%8F/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>[藏]再谈JavaScript中的闭包</title>
      <link>http://blog.leaver.me/2014/04/26/%E8%97%8F%E5%86%8D%E8%B0%88javascript%E4%B8%AD%E7%9A%84%E9%97%AD%E5%8C%85/</link>
      <pubDate>Sat, 26 Apr 2014 16:36:28 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/04/26/%E8%97%8F%E5%86%8D%E8%B0%88javascript%E4%B8%AD%E7%9A%84%E9%97%AD%E5%8C%85/</guid>
      <description>&lt;p&gt;之前读js的时候总是感觉不清楚，近日决定重新攻读，看到这篇文章之后，我明白了某大神说的那句话，如果你不能向一个6岁的小朋友讲明白。那么这件事情你一定不明白。还有就是如果你必须理解一个闭包才会使用它，那么这个闭包设计本身就是失败的。情赏析本文。相当精彩。&lt;/p&gt;
&lt;p&gt;JavaScript中函数的重要性毋庸置疑。在理解了JavaScript中的函数之后，非常重要的地点就是理解我们怎样使用函数来创建闭包。一直以来，闭包都是JavaScript新手学习时的一个难点所在，它位于JavaScript函数与变量作用域交叉的一个灰色地带：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/04/1389597690904-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.20.17.png&#34;&gt;&lt;img alt=&#34;1389597690904-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.20.17&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/a6b5c488378f9e3aa825f07d0a699f5ba6c72afd.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;本文将尽可能简单的方法讲述关于JavaScript闭包的那些事情，使用的代码也非常的简单。如果一开始就讲述闭包的概念，只会使得你更加的困惑。所以我们就从一个我们熟悉的领域开始，慢慢的向闭包的邪恶领域前进，看看我们在那里能发现什么。&lt;/p&gt;
&lt;p&gt;下面开始我们的冒险之旅吧！&lt;/p&gt;
&lt;h1 id=&#34;函数中的函数&#34;&gt;函数中的函数&lt;/h1&gt;
&lt;p&gt;我们要做的第一件事情是理解当你在函数中创建了函数并且从函数内部返回一个函数时究竟发生了什么。首先我们来快速的回顾一下函数。&lt;/p&gt;
&lt;p&gt;看下面的代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;calculateRectangleArea&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;length&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;width&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;
    &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;return&amp;lt;/span&amp;gt; length&amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;*&amp;lt;/span&amp;gt;width&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;   

&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; roomArea &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;calculateRectangleArea&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token number&amp;quot; style=&amp;quot;color: #990055;&amp;quot;&amp;gt;10&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token number&amp;quot; style=&amp;quot;color: #990055;&amp;quot;&amp;gt;10&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;  
&amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;alert&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;roomArea&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;   
`&amp;lt;/pre&amp;gt;

calculateRectangleArea函数接收两个参数并且返回这两个参数的乘积。在这个例子中没我们将返回的数赋值给了变量roomArea。

当代码运行之后，roomArea变量包含了10乘10的结果，也就是100：

[![1389597709290-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.20.27](/images/5465c1b36f5c205fe7fbf69cde8ce0a292c44992.png)](http://leaverimage.b0.upaiyun.com/2014/04/1389597709290-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.20.27.png)

正如你所知道的，一个函数可以返回任何东西。在这个例子中，我们返回了一个数。你可以返回一些文本（也就是字符串），undefined，一个自定义对象等等。只要调用函数的代码知道怎么处理返回的值，你可以做任何你想做的事情。你甚至可以返回另一个函数。我们下面就来看一个这样的例子：

&amp;lt;pre class=&amp;quot; language-javascript&amp;quot; style=&amp;quot;color: black;&amp;quot;&amp;gt;`&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;youSayGoodBye&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;
    &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;alert&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token string&amp;quot; style=&amp;quot;color: #669900;&amp;quot;&amp;gt;&#39;Good Bye!&#39;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;

    &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;andISayHello&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;
        &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;alert&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token string&amp;quot; style=&amp;quot;color: #669900;&amp;quot;&amp;gt;&#39;Hello!&#39;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
    &amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;

    &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;return&amp;lt;/span&amp;gt; andISayHello&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt; 
&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;
`&amp;lt;/pre&amp;gt;

你可以在函数内部包括函数。在这个例子中，我们的youSayGoodBye函数包含了一个alert语句以及另一个叫做andTSayHello的函数：

[![1389597723104-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.25.09](/images/7dec0726d4e268a59b287fce13db84f2bda5c50e.png)](http://leaverimage.b0.upaiyun.com/2014/04/1389597723104-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.25.09.png)

有趣的地方是当youSayGoodBye函数调用时返回了什么东西。它返回了andISayHello函数：

&amp;lt;pre class=&amp;quot; language-javascript&amp;quot; style=&amp;quot;color: black;&amp;quot;&amp;gt;`&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;youSayGoodBye&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;
    &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;alert&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token string&amp;quot; style=&amp;quot;color: #669900;&amp;quot;&amp;gt;&#39;Good Bye!&#39;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;

    &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;andISayHello&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;
        &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;alert&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token string&amp;quot; style=&amp;quot;color: #669900;&amp;quot;&amp;gt;&#39;Hello!&#39;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
    &amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;

    &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;return&amp;lt;/span&amp;gt; andISayHello&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;   
`&amp;lt;/pre&amp;gt;

下面我们调用这个函数，并且让一个变量指向这个函数的调用结果：

&amp;lt;pre class=&amp;quot; language-javascript&amp;quot; style=&amp;quot;color: black;&amp;quot;&amp;gt;`&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; something &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;youSayGoodBye&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;   
`&amp;lt;/pre&amp;gt;

在这行代码运行的时候，youSayGoodBye函数中的所有代码同时也在运行。这意味着，你可以看到一个对话框（由于alert）说Good Bye！：

[![1389597744293-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.29.06](/images/1826cf206cce86d88a6a324d2624ae277929390d.png)](http://leaverimage.b0.upaiyun.com/2014/04/1389597744293-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.29.06.png)

当运行结束之后，andISayHello函数将会被创建并且返回。在这个时候，变量something只关注一个东西，这个东西就是andISayHello函数：

[![1389597757035-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.40.17](/images/907b52e917c6617d2d66519f443e640b61d10472.png)](http://leaverimage.b0.upaiyun.com/2014/04/1389597757035-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.40.17.png)

由于something现在指向一个函数，因此你可以通过括号标示符调用它：

&amp;lt;pre class=&amp;quot; language-javascript&amp;quot; style=&amp;quot;color: black;&amp;quot;&amp;gt;`&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; something &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;youSayHello&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;something&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;   
`&amp;lt;/pre&amp;gt;

当你这么做的时候，返回的内部函数（也就是andISayHello）将会执行。和前面一样，你将会看到一个对话框，但是对话框这次说的是Hello！– 这是由于内部的alert决定的：

[![1389597771981-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.42.50](/images/d0674b8248c110e71cbc5c6878af799538446963.png)](http://leaverimage.b0.upaiyun.com/2014/04/1389597771981-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%881.42.50.png)

上面提到的所有东西都很直观。唯一你可能觉得比较新的地方是一旦一个函数返回一个值，这个函数就不再存在了。唯一存在的东西是返回值。

现在我们已经接近闭包的邪恶领域了。在下一部分中，我们将扩展前面提到的代码来看看一个变形的例子。

# 内部函数不是自包含函数的情况

在前面的例子中，你的andISayHello函数是一个自包含函数并且不依赖于外部函数的任何变量或状态：

&amp;lt;pre class=&amp;quot; language-javascript&amp;quot; style=&amp;quot;color: black;&amp;quot;&amp;gt;`&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;youSayGoodBye&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;

    &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;alert&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token string&amp;quot; style=&amp;quot;color: #669900;&amp;quot;&amp;gt;&amp;quot;Good Bye!&amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;

    &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;andISayHello&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;
        &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;alert&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token string&amp;quot; style=&amp;quot;color: #669900;&amp;quot;&amp;gt;&amp;quot;Hello!&amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
    &amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;

    &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;return&amp;lt;/span&amp;gt; andISayHello&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;   
`&amp;lt;/pre&amp;gt;

在现实的很多场景中，几乎没有这样的自包含函数的例子。你经常会发现需要在内部函数和外部函数之间共享变量和数据。为了强调这一点，我们看看下面的例子：

&amp;lt;pre class=&amp;quot; language-javascript&amp;quot; style=&amp;quot;color: black;&amp;quot;&amp;gt;`&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;stopWatch&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;
    &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; startTime &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; Date&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;now&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;

    &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;getDelay&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;
        &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; elapsedTime &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; Date&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;now&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;-&amp;lt;/span&amp;gt; startTime&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
        &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;alert&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;elapsedTime&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
    &amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;

    &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;return&amp;lt;/span&amp;gt; getDelay&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;   
`&amp;lt;/pre&amp;gt;

这个例子展示了一个简单地测量消耗的时间的方式。在stopWatch函数中，你有一个startTime变量来被赋值为Date.now()：

&amp;lt;pre class=&amp;quot; language-javascript&amp;quot; style=&amp;quot;color: black;&amp;quot;&amp;gt;` &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; startTime &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; Date&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;now&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;   
`&amp;lt;/pre&amp;gt;

你也有一个叫做getDelay的内部函数：

&amp;lt;pre class=&amp;quot; language-javascript&amp;quot; style=&amp;quot;color: black;&amp;quot;&amp;gt;`&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;getDelay&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;
  &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; elapsedTime &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; Date&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;now&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;-&amp;lt;/span&amp;gt; startTime&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
  &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;alert&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;elapsedTime&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;
`&amp;lt;/pre&amp;gt;

getDelay函数展示了一个包含当前时间Date.now()和前面定义的开始时间startTime之间间隔的对话框。

回到外部函数stopWatch()，在运行结束之前发生的最户一件事情是返回getDelay函数。正如你所见的，这里的这段代码和先前的例子非常类似。你有一个外部函数，你有一个内部函数，然后外部函数返回了内部函数。

现在，为了弄清楚，stopWatch函数是怎么运行的，我们添加下面的代码：

&amp;lt;pre class=&amp;quot; language-javascript&amp;quot; style=&amp;quot;color: black;&amp;quot;&amp;gt;`&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; timer &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;stopWatch&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;token comment&amp;quot; style=&amp;quot;color: #708090;&amp;quot; spellcheck=&amp;quot;true&amp;quot;&amp;gt;
// 做一些消耗时间的式
&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;for&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; i &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token number&amp;quot; style=&amp;quot;color: #990055;&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt; i &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;&amp;amp;lt;&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token number&amp;quot; style=&amp;quot;color: #990055;&amp;quot;&amp;gt;1000000&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt; i&amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;++&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;
    &amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; foo &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; Math&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;random&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;*&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token number&amp;quot; style=&amp;quot;color: #990055;&amp;quot;&amp;gt;10000&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;token comment&amp;quot; style=&amp;quot;color: #708090;&amp;quot; spellcheck=&amp;quot;true&amp;quot;&amp;gt;
// 调用返回函数
&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;timer&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;    
`&amp;lt;/pre&amp;gt;

如果你运行这个例子，你将看到一个对话框展示从初始化到timer函数被调用之间时间间隔的对话框。你的for循环接收时候，timer变量像一个函数一样被调用：

[![1389597808064-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%882.50.43](/images/69023707f410b23b639f61b5118be955427c17b9.png)](http://leaverimage.b0.upaiyun.com/2014/04/1389597808064-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%882.50.43.png)

基本上，你现在有了一个秒表可以用来计算一个长时间运行的操作花费了多长时间。

现在你看到我们的简单的秒表例子已经运行起来了，我们回到stopWatch函数看看实际上发生了什么。正如前面所提到的，上面的例子和前面的youSayGoodBye/andISayHello例子很相似。要注意的一点是当getDelay函数返回并赋值给timer变量时发生了什么。

[![1389597819038-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%882.55.09](/images/755cd1da19a41e45c319b357219d99a470d65f44.png)](http://leaverimage.b0.upaiyun.com/2014/04/1389597819038-%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202014-01-13%20%E4%B8%8B%E5%8D%882.55.09.png)

外部函数stopWatch不再起作用，time人变量被绑定到了getDelay函数。现在，有区别的地方来了。getDelay函数依赖于外部函数stopWatch上下文中的startTime变量：

&amp;lt;pre class=&amp;quot; language-javascript&amp;quot; style=&amp;quot;color: black;&amp;quot;&amp;gt;`&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;

&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; startTime &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; Date&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;now&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;  

&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;

&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; elapsedTime &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; Date&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;now&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;-&amp;lt;/span&amp;gt; startTime&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;   

&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;  
`&amp;lt;/pre&amp;gt;

当getDelay函数被返回时外部函数stopWatch函数不再器作用，那么下面的这行代码又发生了什么？

&amp;lt;pre class=&amp;quot; language-javascript&amp;quot; style=&amp;quot;color: black;&amp;quot;&amp;gt;`&amp;lt;span class=&amp;quot;token keyword&amp;quot; style=&amp;quot;color: #0077aa;&amp;quot;&amp;gt;var&amp;lt;/span&amp;gt; elapsedTime &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; Date&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token function&amp;quot;&amp;gt;now&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&amp;quot;token operator&amp;quot; style=&amp;quot;color: #a67f59;&amp;quot;&amp;gt;-&amp;lt;/span&amp;gt; startTime&amp;lt;span class=&amp;quot;token punctuation&amp;quot; style=&amp;quot;color: #999999;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;   
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在这个上下文中，看起来startTime变量没有被定义。但是，这段代码显然正常运行了，因此这里存在一些其他的东西。这里提到的“其他的东西”值得就是害羞而神秘的闭包。我们来看看究竟发生了什么似的我们的startTime变量储存了一个实际的值而不是undefined。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[藏]跨行清算系统的实现原理</title>
      <link>http://blog.leaver.me/2013/12/14/%E8%97%8F%E8%B7%A8%E8%A1%8C%E6%B8%85%E7%AE%97%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86/</link>
      <pubDate>Sat, 14 Dec 2013 18:24:12 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/12/14/%E8%97%8F%E8%B7%A8%E8%A1%8C%E6%B8%85%E7%AE%97%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86/</guid>
      <description>&lt;p&gt;本文来自&lt;a href=&#34;http://www.cnblogs.com/aigongsi/p/3439766.html&#34;&gt;God Is Coder&lt;/a&gt;，通过这篇文章我算是理解了跨行清算系统逻辑，非常非常好。&lt;/p&gt;
&lt;p&gt;最近看了很多银联方面的清算系统的设计原理，对于跨行清算系统有了很大的了解，写这篇文章的目的是在于从一个程序员的角度去思考一个跨行清算系统的架构是如何实现的以及整个过程中我们有哪些思想是可以借鉴的。由于金融里面涉及到太多的专业名词，包括借贷，备付金，头寸，调拨等等，这里不会涉及到这些，取而代之的是以大家可以理解的概念去解释。&lt;/p&gt;
&lt;p&gt;下面简单的介绍一下两种跨行清算系统的实现原理以及特点。一种跨清算系统是我们最熟悉的银联，还有一种是越来越流行的第三方支付系统，比较典型的是快钱。&lt;/p&gt;
&lt;p&gt;首先来拿生活中的一个非常常见的例子来说明跨行清算的整个过程，这里面不涉及交易费等其他概念。&lt;/p&gt;
&lt;h2 id=&#34;跨行取款流程&#34;&gt;&lt;strong&gt;跨行取款流程&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;张三是工行的持卡人，他需要取现金，但是找不到工行的ATM机器，发现附近有建行的ATM机器，他只能去建行取款，整个过程就是跨行清算的过程，我们以这个场景为例，分析一下业务流程，具体交互流程见下面一张图。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-21B3CB2A3-1863-403C-AA5A-F1F49E7EF416.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-21B3CB2A3-1863-403C-AA5A-F1F49E7EF416&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2128716c2c0bc979bd671885c0cb16e5ee93d09e.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;工行持卡人张三在建行ATM机器取款100，ATM请求建行主机，由于是工行的卡，建行不识别，只能请求工行去处理，工行识别持卡人账户并扣款100，然后通知建行，建行则通知atm吐钱。&lt;/p&gt;
&lt;p&gt;这里整个系统要解决两个问题：&lt;/p&gt;
&lt;p&gt;1 建行如何与工行通信&lt;/p&gt;
&lt;p&gt;2 建行和工行之间如何清算，如上图结果，工行欠建行100.&lt;/p&gt;
&lt;p&gt;整个系统的分析基于以上两个问题，下面首先解决是通信问题&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;跨行通信的两种模式&#34;&gt;跨行通信的两种模式&lt;/h2&gt;
&lt;p&gt;我们先假设工行提供接口，只需要建行发送指约定格式的报文，即可于工行通信，这种相当于建行直接通过接口方式与工行通信。如果是这种方式，只能解决建行和工行的单向通信，如果工行和建行通信，则工行要发送建行指定的通信报文格式。可是大家想想，如果银行更多怎么办，下面是三家银行间的通信&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-239A9848E-13A0-4F15-ABEB-F1CE91BBAD73.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-239A9848E-13A0-4F15-ABEB-F1CE91BBAD73&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/bf16b6e107e301f75d8484ce0e0f98ed3f685027.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;当有三家银行的时候，通信链路就有3*2=6条，当银行越来越多的时候，这种点对点的通信变的越来越复杂，每新增一家银行，他要做之前银行都要做的很多重复性的劳动，这样的成本非常高，也不经济，那么必须出现一个网络，它能够接入所有的银行，新的银行只需要接入这个网络，就可以和其他所有的银行进行通信。&lt;/p&gt;
&lt;p&gt;先把这个网络成为通信网络，这种通信网络有两种方式可以连接所有的银行&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 这个通信网络定义标准接口，所有的银行都必须实现这个通信网络定义的api，新的银行如果想要接入这个通信网络，必须实现通信接口约定的协议。简称公共接口模式&lt;/li&gt;
&lt;li&gt;2 这个通信网络主动去连接所有的银行的接口，把所有银行的接口信息都接入里面，就像一个适配器，新的银行如果想要接入这个通信网络，这个通信网络必须主动联系银行，按照银行的接口协议实现通信，简称适配器模式。
下面一幅图演示了这两种模式的不同：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-27BDB9C58-65C9-4F58-B9B0-EA37D977317E.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-27BDB9C58-65C9-4F58-B9B0-EA37D977317E&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/11ace11b09acce70d8eaead337a87ebb868513a8.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;对于这两模式，主要博弈就在于谁强谁弱。显然第三方支付公司属于适配器模式，需要一家一家银行去接入，至于银联，个人认为应该是第一种模式，这种对于银联这种需要稳定的系统来说是最具有优势的。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;跨行清算保证金模式&#34;&gt;跨行清算保证金模式&lt;/h2&gt;
&lt;p&gt;解决了通信问题，下面就看如何解决资金的清算问题。一种简单的方案就是工行在建行里面开设一个保证金账户，用这个账户去偿还在整个跨行交易中应付给建行的资金。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-288169047-B15D-422F-828E-685ADF9207D7.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-288169047-B15D-422F-828E-685ADF9207D7&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ee7b5387f30e0221c9366cf68d72d03cca9fa2fb.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;从上图来看，这种方案确实可行。只需要工行在建行里面放足额的保证金，就可以满足跨行的费用。但是这里面实际上存在非常多的问题，&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 如果银行越来也多，每个银行都要在其他银行存钱，太不经济了&lt;/li&gt;
&lt;li&gt;2 保证金需要放多少资金？如果一直都没有发生跨行交易，工行就亏大发了&lt;/li&gt;
&lt;li&gt;3 如果保证金不够怎么办？交易失败还是记应收款？
对于第一个问题假设银行越来越多，会导致工行需要在其他每个银行里面都开设保证金账户（见下图），是一个很不经济的方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-266D7CC71-8C84-4621-B234-3E06FAC5856F.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-266D7CC71-8C84-4621-B234-3E06FAC5856F&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/07c21a5d4f416fa7b3b34b4667bcb02a08a452fd.png&#34;&gt;&lt;/a&gt;说明这个在其他银行存保证金的方案是不可行的，和之前通信的问题一样，是不是可以把所有的银行保证金账户单独管理起来，统一放置在一起，方便各个银行之间的清算。我们暂时把这个系统称之为保证金系统。&lt;/p&gt;
&lt;h2 id=&#34;保证金系统&#34;&gt;保证金系统&lt;/h2&gt;
&lt;p&gt;保证金就是方便各个银行之间的清算，需要单独由一个系统进行管理，解决了跨行之间保证金存放的问题。每个银行只需要在保证金系统中存点钱就可以了。保证金系统也有两种模式。先看看比较好理解的第一种模式：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-2EB1C0D6C-C30F-4B7D-A120-7CB46AC33DD3.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-2EB1C0D6C-C30F-4B7D-A120-7CB46AC33DD3&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b420275350a8aa8888110b745a1426787f9a750d.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在这种模式下，银行先把一部分钱存放在保证金系统里面，同时银行内部建立一个虚拟账户，记录存放了多少钱，主要是方便对账，万一这个保证金系统钱算错了怎么办。你可以想象一下，银行是很小气的，为啥愿意把钱存放到这保证金系统里面，这部分钱干啥不好，能够银行这么干的只有国家了，这个系统就是央行的备付金管理系统。每个新增的银行都要存一份钱在这里。&lt;/p&gt;
&lt;p&gt;另外一种方案是倒过来思考，既然没有牛逼的央行作支撑，那可以在每个商业银行都建立一个账户，用这个账户负责和银行进行清算。每新增一家银行，就在那个银行里面开一个保证金账户。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-2EBA5972D-06C6-4DC7-A7E4-4CC68455988B.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-2EBA5972D-06C6-4DC7-A7E4-4CC68455988B&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2ed236969650d9d6c981c7a933ca69a0b0aa982a.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这两种方式有本质的不同，一个是银行把资金的一部分转出到保证金，银行建立虚拟账户和保证金里面真实的资金映射。一个是保证金系统把资金转出到各个银行，自己内部建立一个虚拟账户和银行中真实的资金账户进行映射。这个间接的银行了后续的对账机制，这里先不叙述。&lt;/p&gt;
&lt;p&gt;所有的第三方支付公司跨行清算的流程都是第二种方式，只有国家级清算公司（比如银联）是第一种方式，这是一种资源和权力上的不平等，不过是可以理解的。&lt;/p&gt;
&lt;h2 id=&#34;清算系统&#34;&gt;清算系统&lt;/h2&gt;
&lt;p&gt;保证金系统解决了保证金存放的问题，接下来就是解决如何清算的问题。假设保证金转账是实时的，就要面对上面说的问题，保证金不够的情况下，跨行交易是成功还是失败。这是一个业务上问题，有很多种解决方案，我们暂不说。从技术上来讲，如果每一笔交易都要保证金实时记账，那么保证金系统的负载太大，事务如何保证等等一些列的问题。所以一个最简单的方案就是：一天结算一次。&lt;/p&gt;
&lt;p&gt;每天由一个系统记录这些跨行交易信息，汇总出来，统一记账。这样一天只需要调用一次保证金系统即可。那么整个清算过程则是下面的流程：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;1 系统T日发生建行和工行的跨行交易100
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-208F9F26D-11BC-4BCA-9FAD-F5C9F7B9691C.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-208F9F26D-11BC-4BCA-9FAD-F5C9F7B9691C&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/4c745f5c7b8a40a840d975f5ac5a0e0871e8a2dc.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2 清算系统T+1日汇总T日工行和建行之间发生的交易明细数据，并且发这些数据发给建行和工行进行确认
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-2111356A9-ECA8-490A-977A-1FCD613F054F.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-2111356A9-ECA8-490A-977A-1FCD613F054F&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/1982182c16c49a40f6f81c9839c260a0b599296c.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3 工行建行分别对明细对账确认之后，通知清算系统确认交易明细无误，清算系统开始清算，调用保证金支付系统转账。&lt;/li&gt;
&lt;li&gt;4 清算完成之后，工行和建行分别获取保证金系统的真实金额和自身系统内部的映射账户进行余额对账。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-2C84544CD-AE52-4D98-999C-C8B587B3E6AE.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-2C84544CD-AE52-4D98-999C-C8B587B3E6AE&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/c6fbba7cf0732085b9fc6a72eac7df350c736d08.png&#34;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;清算中心最主要干得事情就是统计谁欠谁多少钱，以及触发保证金系统的调拨操作。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;对账流程&#34;&gt;对账流程&lt;/h2&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;p&gt;以上就是一个简单的跨行清算系统的雏形，从一个就简单的例子入手，说明一个清算过程。目前银联的第三方支付公司的清算过程大致如此，但是实现细节远比这个复杂。但是一个基本的清算系统的本质模型大体上是不会变的。当然这个只是对于同币种的清算，不同币种或者虚拟货币的清算会涉及到汇率的问题，这些就很复杂，有机会在研究一下，后续在分享。&lt;/p&gt;
&lt;p&gt;PS：以上很多名词都是自己的随意写的，里面很多专业名词这里不提及，有兴趣的可以自己去了解。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[藏]Class.getResource和ClassLoader.getResource不同点</title>
      <link>http://blog.leaver.me/2013/12/14/%E8%97%8Fclass.getresource%E5%92%8Cclassloader.getresource%E4%B8%8D%E5%90%8C%E7%82%B9/</link>
      <pubDate>Sat, 14 Dec 2013 18:18:53 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/12/14/%E8%97%8Fclass.getresource%E5%92%8Cclassloader.getresource%E4%B8%8D%E5%90%8C%E7%82%B9/</guid>
      <description>&lt;p&gt;有一次遇到了，查了查。&lt;a href=&#34;http://www.cnblogs.com/yejg1212/p/3270152.html&#34;&gt;原文地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Java中取资源时，经常用到Class.getResource和ClassLoader.getResource，这里来看看他们在取资源文件时候的路径问题。&lt;/p&gt;
&lt;h2 id=&#34;classgetresourcestring-path&#34;&gt;Class.getResource(String path)&lt;/h2&gt;
&lt;div&gt;
&lt;pre&gt;path不以’/&#39;开头时，默认是从此类所在的包下取资源；
path  以’/&#39;开头时，则是从ClassPath根下获取；&lt;/pre&gt;
&lt;/div&gt;
什么意思呢？看下面这段代码的输出结果就明白了：
&lt;div&gt;
&lt;pre&gt;package testpackage;
public class TestMain {
    public static void main(String[] args) {
        System.out.println(TestMain.class.getResource(&#34;&#34;));
        System.out.println(TestMain.class.getResource(&#34;/&#34;));
    }
}&lt;/pre&gt;
&lt;/div&gt;
输出结果：
&lt;div&gt;
&lt;pre&gt;file:/E:/workspace/Test/bin/testpackage/
file:/E:/workspace/Test/bin/&lt;/pre&gt;
&lt;/div&gt;
上面说到的【path以’/&#39;开头时，则是从ClassPath根下获取；】在这里就是相当于bin目录(Eclipse环境下)。
&lt;p&gt;再来一个实例，假设有如下Project结构：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/o_PackageStructure1.png&#34;&gt;&lt;img alt=&#34;o_PackageStructure1&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/94eb328bce2cf9ff32430cc4075af46091202a22.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;如果我们想在TestMain.java中分别取到1~3.properties文件，该怎么写路径呢？代码如下：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;package testpackage;

public class TestMain {

    public static void main(String[] args) {
        // 当前类(class)所在的包目录
        System.out.println(TestMain.class.getResource(&#34;&#34;));
        // class path根目录
        System.out.println(TestMain.class.getResource(&#34;/&#34;));

        // TestMain.class在&amp;lt;bin&amp;gt;/testpackage包中
        // 2.properties  在&amp;lt;bin&amp;gt;/testpackage包中
        System.out.println(TestMain.class.getResource(&#34;2.properties&#34;));

        // TestMain.class在&amp;lt;bin&amp;gt;/testpackage包中
        // 3.properties  在&amp;lt;bin&amp;gt;/testpackage.subpackage包中
        System.out.println(TestMain.class.getResource(&#34;subpackage/3.properties&#34;));

        // TestMain.class在&amp;lt;bin&amp;gt;/testpackage包中
        // 1.properties  在bin目录（class根目录）
        System.out.println(TestMain.class.getResource(&#34;/1.properties&#34;));
    }
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;※Class.getResource和Class.getResourceAsStream在使用时，路径选择上是一样的。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;classgetclassloadergetresourcestring-path&#34;&gt;Class.getClassLoader（）.getResource(String path)&lt;/h2&gt;
&lt;div&gt;
&lt;pre&gt;path不能以’/&#39;开头时；
path是从ClassPath根下获取；&lt;/pre&gt;
&lt;/div&gt;
还是先看一下下面这段代码的输出：
&lt;div&gt;
&lt;pre&gt;package testpackage;
public class TestMain {
    public static void main(String[] args) {
        TestMain t = new TestMain();
        System.out.println(t.getClass());
        System.out.println(t.getClass().getClassLoader());
        System.out.println(t.getClass().getClassLoader().getResource(&#34;&#34;));
        System.out.println(t.getClass().getClassLoader().getResource(&#34;/&#34;));//null
    }
}&lt;/pre&gt;
&lt;/div&gt;
输出结果：
&lt;div&gt;
&lt;pre&gt;class testpackage.TestMain
sun.misc.Launcher$AppClassLoader@1fb8ee3
file:/E:/workspace/Test/bin/
null&lt;/pre&gt;
&lt;/div&gt;
从结果来看【TestMain.class.getResource(&#34;/&#34;) == t.getClass().getClassLoader().getResource(&#34;&#34;)】
&lt;p&gt;如果有同样的Project结构&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/o_PackageStructure.png&#34;&gt;&lt;img alt=&#34;o_PackageStructure&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/46e184c9601d96bbb9fbb19e475c7909c85fe52c.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;使用Class.getClassLoader（）.getResource(String path)可以这么写：&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;package testpackage;
&lt;p&gt;public class TestMain {
public static void main(String[] args) {
TestMain t = new TestMain();
System.out.println(t.getClass().getClassLoader().getResource(&amp;quot;&amp;quot;));&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    System.out.println(t.getClass().getClassLoader().getResource(&amp;quot;1.properties&amp;quot;));
    System.out.println(t.getClass().getClassLoader().getResource(&amp;quot;testpackage/2.properties&amp;quot;));
    System.out.println(t.getClass().getClassLoader().getResource(&amp;quot;testpackage/subpackage/3.properties&amp;quot;));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&amp;nbsp;
&lt;p&gt;※Class.getClassLoader（）.getResource和Class.getClassLoader（）.getResourceAsStream在使用时，路径选择上也是一样的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[藏]图文并茂详解Eclipse断点</title>
      <link>http://blog.leaver.me/2013/11/16/%E8%97%8F%E5%9B%BE%E6%96%87%E5%B9%B6%E8%8C%82%E8%AF%A6%E8%A7%A3eclipse%E6%96%AD%E7%82%B9/</link>
      <pubDate>Sat, 16 Nov 2013 14:21:11 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/11/16/%E8%97%8F%E5%9B%BE%E6%96%87%E5%B9%B6%E8%8C%82%E8%AF%A6%E8%A7%A3eclipse%E6%96%AD%E7%82%B9/</guid>
      <description>&lt;p&gt;本文转自：&lt;a href=&#34;http://my.oschina.net/colorleaf/blog/176569&#34;&gt;http://my.oschina.net/colorleaf/blog/176569&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这个算说的比较清楚的了，虽然简单但是很有用。收藏一下。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;详解Eclipse断点&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;大家肯定都用过Eclipse的调试的功能，在调试的过程中自然也无法避免要使用断点(breakpoint)，但不知是否对Eclipse中各类断点都有所了解。本篇图文并茂地介绍了Eclipse中全部类型的断点，及其设置，希望对大家有所帮助。(2011.11.20)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 示例程序&lt;/strong&gt;
BreakpointDemo是一个臆造的应用程序，只是为了便于讲解Eclipse中各类断点的使用罢了。其代码如下图所示，
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153245_BTUJ.png&#34;&gt;&lt;img alt=&#34;15153245_BTUJ&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/abd1d53612eeef8d1feccdf17a894d3e71d41941.png&#34;&gt;&lt;/a&gt;
BreakpointDemo主要包含两个方法：
[1]setValue，该方法根据指定的次数(count)，对成员变量value进行赋值，值的范围为0-9的随机整数。
[2]printValue，该方法会调用setValue()对value进行赋值，并打印出value的值；但，如果value能被3整除，那么就会抛出IllegalArgumentException异常。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Line Breakpoint&lt;/strong&gt;
Line Breakpoin是最简单的Eclipse断点，只要双击某行代码对应的左侧栏，就对该行设置上断点。此处，对第20行代码设置上Line Breakpoint，如下图所示，
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153245_zkOp.png&#34;&gt;&lt;img alt=&#34;15153245_zkOp&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ca7da4e9038334e0603072298cbaf834326da937.png&#34;&gt;&lt;/a&gt;
可以为Line Breakpoint设置一个条件，那么当程序运行到该断点时，只有满足设定的条件，才会被中断。右键点击第20行的断点，选择&amp;quot;Breakpoint Properties&amp;hellip;&amp;quot;
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153245_I2Pe.png&#34;&gt;&lt;img alt=&#34;15153245_I2Pe&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ff95dcb0130a35d3e293a52487e4109316cba1f8.png&#34;&gt;&lt;/a&gt;
在弹出的属性对话框中，勾选上&amp;quot;Conditional&amp;quot;，然后在文本框中输入&amp;quot;count % 2 == 0&amp;quot;。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_rJtm.png&#34;&gt;&lt;img alt=&#34;15153246_rJtm&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/4f5d2d716473a55f1e3b96a59ac07f700657452a.png&#34;&gt;&lt;/a&gt;
该条件表示，当程序运行到第20行时，只有当count为偶数时，程序才会被中断。细心地话，你会发现该断点的图标发生了改变，多了一个问号。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_5APe.png&#34;&gt;&lt;img alt=&#34;15153246_5APe&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/e3d69e5d5b31edbf729ce4522f9b21e2f5024f17.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Watchpoint&lt;/strong&gt;
Line Breakpoint关注于程序运行的&amp;quot;过程&amp;quot;，大家也常把使用这种断点的调试称为单步调试。但有时候，我们对程序的运行过程不太了解，可能也不太关心，不能确定在什么地方设置断点比较合适，而可能比较关注某个关键变量的变化或使用。此时，就可以为该变量设置一种特殊的断点&amp;ndash;Watchpoint。在此示例，我们最关心的就是成员变量value的值，那么就可以为它设置一个Watchpoint，双击第9行代码对应的左侧栏就可以了。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_zzEM.png&#34;&gt;&lt;img alt=&#34;15153246_zzEM&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/082e1647ca341b0f3549dcfc136ce278d73f4acb.png&#34;&gt;&lt;/a&gt;
使用在2中所提及的方法，查看该断点的属性，
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_e1gH.png&#34;&gt;&lt;img alt=&#34;15153246_e1gH&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/f268f9ed80a672eeb51d164658a971d6777989b9.png&#34;&gt;&lt;/a&gt;
默认地，当该变量被访问或它的值被修改时，程序都会被中断。但在本示例中，只希望当对value的值进行修改时程序才需要被中断，所以取消对&amp;quot;Access&amp;quot;的勾选。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_evtw.png&#34;&gt;&lt;img alt=&#34;15153246_evtw&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/1deb043f0baa72b61a76e794f7acf9d25762112c.png&#34;&gt;&lt;/a&gt;
这时，我们会发现原来的Watchpoin图标也有变化了。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_Sw8K.png&#34;&gt;&lt;img alt=&#34;15153246_Sw8K&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/d2dff57a03768ac00b84dd9bb651e99031d94cdc.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Method Breakpoint&lt;/strong&gt;
与关注对某个变量的访问与修改一样，我们也可以关注程序对某个方法的调用情况，即，可以设置Method Breakpoint。在此处，设置针对方法setValue的Method Breakpoint。同理，双击第11行代码对应的左侧栏即可。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153247_xdH4.png&#34;&gt;&lt;img alt=&#34;15153247_xdH4&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/bd49da0a82d0dc044a917e5b53107b05b36f6378.png&#34;&gt;&lt;/a&gt;
仍然要查看该断点的属性。默认地，只勾选了&amp;quot;Entry&amp;quot;，而没有勾选&amp;quot;Exit&amp;quot;。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153247_W1oy.png&#34;&gt;&lt;img alt=&#34;15153247_W1oy&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/7294186aaa782865383feb3a4e375a5a3b628c27.png&#34;&gt;&lt;/a&gt;
这表示，当刚进入该方法(调用开始)时，程序会被中断；而，离开该方法(调用结束)时，程序并不会被中断。在本示例中，需要同时勾选上&amp;quot;Exit&amp;quot;。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153247_QVwz.png&#34;&gt;&lt;img alt=&#34;15153247_QVwz&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/39f23217e1d0ead7061f1d636b97f52b6ee886fd.png&#34;&gt;&lt;/a&gt;
点击OK之后，可以看到该断点的图标也有所改变。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153247_YRMh.png&#34;&gt;&lt;img alt=&#34;15153247_YRMh&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/bdeda47c131aefb575366c4d23b16b3e0ee59321.png&#34;&gt;&lt;/a&gt;
根据这里的设置，当程序运行到第20行后会在第12行被中断，尽管这里没有显式的断点，但这就是setValue()方法的入口(Entry)。必须注意地是，程序在运行到第16行时不会被中断，尽管它看起来像是setValue()方法的出口(Exit)。实际上，程序会在第17行被中断，这里才是setValue()调用结束的地方。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Exception Breakpoint&lt;/strong&gt;
如果，我们期望某个特定异常发生时程序能够被中断，以方便查看当时程序所处的状态。通过设置Exception Breakpoint就能达到这一目标。本示例故意在第23行抛出了IllegalArgumentException异常，我们期望程序运行到此处时会被中断。但我们不直接为此行代码设置Line Breakpoint，而是为IllegalArgumentException设置Exception Breakpoint。设置Exception Breakpoint的方法与其它类型断点都不同，它不能通过双击左侧栏的方式在代码编辑器上直接进行设置。点击Breakpoints视图右上角形如Ji的图标，
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153247_Wm2U.png&#34;&gt;&lt;img alt=&#34;15153247_Wm2U&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/d4f298befa3d1c0100aef36797c56bbc1d2a423c.png&#34;&gt;&lt;/a&gt;
会弹出如下所示的对话框，
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153248_WgLd.png&#34;&gt;&lt;img alt=&#34;15153248_WgLd&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/04e45e47d1e4248fd2ec8db8b13252e1c196e525.png&#34;&gt;&lt;/a&gt;
在其中选中IllegalArgumentException，并点击OK，这时一个Exception Breakpoint就设置好了。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153248_kE2O.png&#34;&gt;&lt;img alt=&#34;15153248_kE2O&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/fd555622458bbb34ad01929c6a7483768f6b37a8.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;当value为3的倍数时，程序会在第23行被中断，这时我们就能使用调试器来看看value具体是等于0，3或6。&lt;/div&gt;
**6\. Class Load Breakpoint**
还有一种大家平时可能不太用的断点--Class Load Breakpoint，即当某个类被加载时，通过该断点可以中断程序。
[![15153248_2UA6](/images/8158c897f4e784042063a484c7256901902b6c20.png)](http://leaverimage.b0.upaiyun.com/2013/11/15153248_2UA6.png)
&lt;p&gt;&lt;strong&gt;小结&lt;/strong&gt;
上述的Eclipse断点，我们在现实工作中肯定都有意或无意地使用过其中的几种，只是不一定十分了解内情罢了。使用好Eclipse的各种断点，可以把很好地帮助我们分析程序，定位问题。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[藏]社交网络，电子时代的人生绑架者</title>
      <link>http://blog.leaver.me/2013/05/13/%E8%97%8F%E7%A4%BE%E4%BA%A4%E7%BD%91%E7%BB%9C%E7%94%B5%E5%AD%90%E6%97%B6%E4%BB%A3%E7%9A%84%E4%BA%BA%E7%94%9F%E7%BB%91%E6%9E%B6%E8%80%85/</link>
      <pubDate>Mon, 13 May 2013 06:31:43 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/05/13/%E8%97%8F%E7%A4%BE%E4%BA%A4%E7%BD%91%E7%BB%9C%E7%94%B5%E5%AD%90%E6%97%B6%E4%BB%A3%E7%9A%84%E4%BA%BA%E7%94%9F%E7%BB%91%E6%9E%B6%E8%80%85/</guid>
      <description>&lt;p&gt;作者:&lt;a href=&#34;http://www.zhihu.com/people/fu-er&#34;&gt;负二&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;bystander:本文回答了你刷社交网络的内在因素.希望读到的人不只是读到那么简单.&lt;/p&gt;
&lt;p&gt;大家在互相打招呼之前，先各自拿出手机，其中几个人用手机“签到”，然后把“签到”信息转发给在场的每一个人，而另一些人则用手机给饭桌上的菜肴拍照，然后同样转发给在场的每一个人，直到各种提示音消失之后，大家开始一边动筷子，一边心不在焉地聊八卦，如果没有爆炸性的话题出现，吸引在场的每一个人的注意力，那么大家的注意力都会被自己的手机虏获——比如我会收到坐在对面的那人发来的一张用手指画的拙劣的涂鸦，然后让我根据此图猜一个单词。&lt;/p&gt;
&lt;p&gt;现在，一次聚餐的情景差不多就是这样，把一盘菜的照片转发给就坐在你身边和你一起吃饭的那个人，这种事说起来真是要多蠢有多蠢，但人们仍是乐此不疲——当一台饮水机都拥有一个微博账号时，我们意识到任何事情都已经无法阻止网络社交了，无论是美食还是同学聚会。&lt;/p&gt;
&lt;p&gt;大多数热衷于用手机刷新SNS网站的人并不认为对网络社交上瘾是什么问题——他们有种幻觉：需要的时候，我肯定能够克制自己，那肯定比戒烟容易。但事实并非如此，网络社交上瘾与烟瘾截然不同，如果你对它背后的机制有所了解，一定会对它能够利用人类心理的弱点到如此地步深感惊讶——一个正常人只要掉进这个圈套，就几乎不可能不对这玩意上瘾。&lt;/p&gt;
&lt;p&gt;如果你有过在泡论坛时不断刷新页面的经历，你就会明白社交网站的通知系统是一个多么精巧的引人上钩的设计——人们难以容忍等待，他们需要新状态的刺激，现代化的机场都将下飞机口到取行李处的距离设计得要多漫长有多漫长，就是为了避免旅客在取行李处叉着双手等行李，因为“走”比“等”更容易让人接受——而创造通知系统的产品经理们显然深谙此道，只要通知系统不断地给出状态更新的通知，就能够让人每天乖乖地登录，然后长时间地留在你的社交网站上，这一招就像用香肠逗狗一样好用。&lt;/p&gt;
&lt;p&gt;许多人认为社交网站降低了人与人之间交流的成本，促进了信息流动和世界大同——他们显然是被Facebook、新浪微薄之类的网站给蒙骗了；而对人类社会的本质有所了解的人则会同意窥私欲是支撑社交网站的动力之一——有一定道理，人们总是有无穷的动力想去瞧瞧多年不见的老朋友、老同学，或是初恋情人，看他们是不是过得比自己更差，我的表弟曾向我坦白，在他听说前女友离婚的消息后，他曾连续一个月关注她的微博和开心网账号，并且觉得很爽——巴菲特说，竞争并不是推动人类前进的动力，嫉妒才是。&lt;/p&gt;
&lt;p&gt;但实际上，窥私欲在社交网络这盘大菜中顶多只能算是几滴酱油——如果你对人性有更透彻的认识，你会从“把一盘菜的照片转发给和你一起吃饭的每一个人”这一举动上看到更深层次的动机。只有够自恋的人才会认为“我在吃这盘菜”这件事很重要，重要到有必要让每个人知道的地步——不幸的是，这世界上除了抑郁症患者，每个人都够自恋，你只要稍加注意就会发现，社交网络中的大多数信息都与“交流”没半毛钱关系，只是某人发布的“自以为很重要”的自我推销信息而已。根据“人类自我表现理论”，人们的自我表现往往根据相互关系中对方的特点而采取某种相应的对策，人们会不断地调节和控制呈现给其他人的信息，特别是有关自我的信息，以便建立起有利于自己的形象——所以人们会狂热地维护自己的微博形象，对隐私泄露视而不见，而对爱你的家人恶言相向。&lt;/p&gt;
&lt;p&gt;最新的研究表明，热衷社交网络，也很有可能是你不够成功的表现——美国人4个中有3个是Facebook用户，但在可支配财产超过100万美元的人群中，这一比例只有26%，而百万富翁中上Twitter的比例更是只有可怜的3%——心理学家指出，原因可能是财富给予人更多的独立意识，对他人的依赖越少，对他人就越少在意，产生自我关注的倾向。想必扎克伯格自己也不会一天到晚泡在自己的网站上——而这世界上大多数人都“不够成功”，毫无疑问。&lt;/p&gt;
&lt;p&gt;只要看透这一切，你就会明白，社交网络热潮，根本不是什么科技革命，它只不过是人性弱点的一次集中爆发而已，并且在它不为人所见的屁股后面，多多少少都能闻出一丝阴谋家的味道——自由软件基金会主席Richard Stallman认为，基于实名制的Facebook是一个国际寄生项目，而Jonathan Nolan（《盗梦空间》编剧）则在他的新剧中直接说，Facebook的幕后金主其实是CIA，自从全世界的人们都那么乐意泄露隐私后，CIA的工作简单了不少。&lt;/p&gt;
&lt;p&gt;现在看来，远离通知提示音的诱惑，从社交网络那里为自己“赎身”，才是人生正途。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[藏]关于B树的一篇文章</title>
      <link>http://blog.leaver.me/2013/04/01/%E8%97%8F%E5%85%B3%E4%BA%8Eb%E6%A0%91%E7%9A%84%E4%B8%80%E7%AF%87%E6%96%87%E7%AB%A0/</link>
      <pubDate>Mon, 01 Apr 2013 18:12:37 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/04/01/%E8%97%8F%E5%85%B3%E4%BA%8Eb%E6%A0%91%E7%9A%84%E4%B8%80%E7%AF%87%E6%96%87%E7%AB%A0/</guid>
      <description>&lt;p&gt;很多人对B树的理解有很多错误，我看的最多的就是有人混淆二叉树（Binary Tree）和B树（B-Tree）,二叉树是不用简称，也就是BT的，而特殊一点的二叉搜索树才会用BST(Binary Search Tree),至于B-树和B树，这两个其实一样的，英文都是(B-Tree)，注意看中间的-号，这个是国内翻译的问题.所以大家不要被误导.&lt;/p&gt;
&lt;p&gt;Rudolf Bayer 和 Ed McCreight 于1972年，在Boeing Research Labs 工作时发明了B 树，但是他们没有解释B 代表什么意义（如果有的话）.Douglas Comer 解释说: 两位作者从来都没解释过B树的原始意义。我个人觉得很有可能是他的名字，程序员对其作品的一种情结吧.&lt;/p&gt;
&lt;p&gt;这篇文章来自国外,是某大学的CS课程在线的,由于有时候无法访问，我直接提供PDF版,对其构造过程非常清晰.非常非常好的B树教程,图示很多,就不翻译了,强烈推荐阅读！&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=404077&amp;amp;uk=1493685990&#34;&gt;B树讲解&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>[藏]熬就一个字</title>
      <link>http://blog.leaver.me/2013/03/11/%E8%97%8F%E7%86%AC%E5%B0%B1%E4%B8%80%E4%B8%AA%E5%AD%97/</link>
      <pubDate>Mon, 11 Mar 2013 09:44:36 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/03/11/%E8%97%8F%E7%86%AC%E5%B0%B1%E4%B8%80%E4%B8%AA%E5%AD%97/</guid>
      <description>&lt;p&gt;文/冯仑&lt;/p&gt;
&lt;p&gt;男孩子最大的问题，30多岁自己还没有成功。&lt;/p&gt;
&lt;p&gt;现在社会反差特别大，怎么坚守自己的人生目标就特别难，随波逐流总是成本低，但对自己不负责任，不如设定一个特别大的目标，然后熬，一直熬下去。&lt;/p&gt;
&lt;p&gt;熬是个什么概念？&lt;/p&gt;
&lt;p&gt;20多岁刚毕业，你是社会的边缘，什么事都是哥哥、姐姐、30多40多的人在做，你得求这些人；等到30多岁，你开始进入到剧场最后一排，有了一张门票可以看别人演；到40、50岁，就是中排靠前一点的观众，看戏你就可以看的清楚了；你如果要出类拔萃就变成第一排了，再出类拔萃你就成演员了，等到你演完了，别人一鼓掌你也就该下场了。&lt;/p&gt;
&lt;p&gt;20多岁一定要有一个准备，你就是边缘，边缘是尽快拿到入场券。比如说你到了公司，有了一个稳定的职业，或者一个基本稳定的生活，但是你乘自行车、赶公共汽车，这就是入场券，很正常。&lt;/p&gt;
&lt;p&gt;我研究生刚毕业，中间工作八年，每天骑自行车赶到374，然后坐公共汽车，公共汽车下来再走一站地。回头想来不委屈，20多岁肯定是这个过程，如果20岁就跟50岁人一样，那这个戏就乱了，中国十几亿人都这么演的。插队是偶然性，比如像丁磊他是另外一种人生，这种概率极小极小，你可以朝着奋斗。&lt;/p&gt;
&lt;p&gt;成功不是设计出来，是靠信念支撑，加上各种机遇偶然蹦出来了。当你成演员，基本上也该谢幕了，接下来又来了人，这个戏才能不断唱。现在70多岁人基本上又退回到场外了，看他儿子演孙子演，就这么一茬一茬。&lt;/p&gt;
&lt;p&gt;熬要有耐心，熬不是你一个人熬，而是一代人熬。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[E].Net 多线程指南</title>
      <link>http://blog.leaver.me/2013/03/06/e.net-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8C%87%E5%8D%97/</link>
      <pubDate>Wed, 06 Mar 2013 22:28:20 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/03/06/e.net-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8C%87%E5%8D%97/</guid>
      <description>&lt;p&gt;这是codeproject上的一个系列。我看完了。收获匪浅。可惜作者之后未能更新预想中的总结贴，多少有些可惜，不过。此系列非常非常不错。建议想学习.net多线程的看看。&lt;/p&gt;
&lt;p&gt;1.net 多线程介绍 &lt;a href=&#34;http://www.codeproject.com/KB/threads/ThreadingDotNet.aspx&#34;&gt;Introduction into threading in .NET&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2.线程周期/线程优势/陷阱 &lt;a href=&#34;http://www.codeproject.com/KB/threads/ThreadingDotNet2.aspx&#34;&gt;Lifecycle of threads/Threading opportunities/Traps &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;3.线程同步 &lt;a href=&#34;http://www.codeproject.com/KB/threads/ThreadingDotNet3.aspx&#34;&gt;Synchronization&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4.线程池 &lt;a href=&#34;http://www.codeproject.com/KB/threads/ThreadingDotNet4.aspx&#34;&gt;Thread Pools&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;5.UI中的线程应用 &lt;a href=&#34;http://www.codeproject.com/KB/threads/ThreadingDotNet5.aspx&#34;&gt;Threading in UIs (WinForms / WPF / Silverlight)&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>装逼尚未成功，同志仍需努力。</title>
      <link>http://blog.leaver.me/2013/02/25/%E8%A3%85%E9%80%BC%E5%B0%9A%E6%9C%AA%E6%88%90%E5%8A%9F%E5%90%8C%E5%BF%97%E4%BB%8D%E9%9C%80%E5%8A%AA%E5%8A%9B/</link>
      <pubDate>Mon, 25 Feb 2013 21:24:21 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/02/25/%E8%A3%85%E9%80%BC%E5%B0%9A%E6%9C%AA%E6%88%90%E5%8A%9F%E5%90%8C%E5%BF%97%E4%BB%8D%E9%9C%80%E5%8A%AA%E5%8A%9B/</guid>
      <description>&lt;p&gt;　　本文来自&lt;a href=&#34;http://hxyl.net/2013/02/24/zhuangbimeichengong/&#34;&gt;河蟹娱乐&lt;/a&gt;，看到的时候让我想起了《娱乐至死》和《瓦尔登湖》，总之，不打算拯救世界，也不在乎别人装逼，生活什么的，简单最好。文中观点也许略有偏颇，读者自己心中有数即可-bystander&lt;/p&gt;
&lt;p&gt;　　你受过良好的教育，有意无意间说起自己的大学，旁人无一例外纷纷投来艳羡目光。你工作光鲜，不是四大就是4A，不是垄断国企就是全球500强；在一个都是中国人的公司里互相叫对方英文名。你衣食无忧，三个月工资买一LV包；你生活清闲，上班时就像神九的航天员，明明啥事没干还要装出一副很忙的样子；你格调不俗，业余时间不是昆曲就是话剧，不是民谣专场就是妈妈咪呀；你善良正义，身处斗室，胸怀天下，每天吃饱饭就刷刷微博拯救中国。&lt;/p&gt;
&lt;p&gt;　　你用苹果，买个五千块的马脸iPhone，又是贴膜又是镶钻，十天换八个壳；你用谷歌，买个两千块的安卓手机，又是S-OFF又是ROOT，十天刷八个ROM。你关注互联网，精通电子产品，上机锋网威锋网雷锋网，电脑里永远装着十个GTD软件八个思维导图软件，用Instagram记录生活，对乔布斯比对你爸还了解，以果粉自居并喜欢到论坛上问：iOS6完美越狱什么时候出来啊？&lt;/p&gt;
&lt;p&gt;　　你发烧，你还发骚，出门带着IPC，用麻绳绑个随身耳放，再配一对ER4P入耳式耳塞，完全隔音，也不怕被车撞死。嫌不够惹眼？那就换一副时下最流行的魔声Beats Pro头戴式耳机，每一个苹果旗舰店的配件区里都有卖，它颜色鲜艳外形时尚，两个耳朵每边印着一个b，挂在你的头上，真是实至名归。&lt;/p&gt;
&lt;p&gt;　　你叫自己“吃货”，可怜的娃从小在城里长大没吃过什么好东西，为了美食频道里推荐的坑爹路边摊，坐10块钱地铁从城南干到城北。你热爱美食，每次花十分钟炒菜，二十分钟摆盘，三十分钟拍照，拍好导进PhotoShop里用康熙字典体配上两句文言文，传到博客上豆瓣上微博上。&lt;/p&gt;
&lt;p&gt;　　你文艺青年，琴棋书画样样不通，格律没搞懂就敢写古诗词，最爱莎士比亚的英雄双行体。你只到电影院看电影，提到外国电影从不说中文名，也不说英文名，管《指环王》叫LOTR，《蝙蝠侠3》叫TDKR，倍洋气倍有面子。你一听到维瓦尔第的《四季》，就会想起波光粼粼的日内瓦湖和白雪皑皑的阿尔卑斯山。&lt;/p&gt;
&lt;p&gt;　　终于有一天，当你拿着一张音乐会赠票睡死在钢琴声中，当你附庸风雅跑去看毕加索画展却一张画也没看懂，你突然意识到了自己的浅薄。没有金刚钻，怎装瓷器逼？没有付出，哪来收获？&lt;/p&gt;
&lt;p&gt;　　装逼没有那么容易，才会特别让人着迷。&lt;/p&gt;
&lt;p&gt;　　你开始认认真真地看书，时间宝贵，你只看经典，抬手就是中华书局、上海古籍，各种珍本善本影印本，横排版的书不看，简体字的书不看。理论学习也不能落下，商务印书馆汉译世界学术名著丛书买它个几十本回来，黄的绿的橙的蓝的，书架上一排彩虹。&lt;/p&gt;
&lt;p&gt;　　你偷偷把手机铃声从《我的歌声里》换成肖邦的夜曲，王菲、张国荣的CD扔掉，你万青，你痛仰，你Pink Floyd，你Guns N’ Roses，你从流行听到爵士，从摇听到古典，别人问起你最喜欢的歌手，你四十五度角仰望星空，眼神虔诚地说出一句：“In Bach We Trust。”念到Bach的ch时上腭抬高，发成“喝哈”轻读加连读的效果，一口纯正的小舌音，德味！&lt;/p&gt;
&lt;p&gt;　　数码单反是不能再用了，现在连旅游团的大叔大妈们都人手一只无敌兔了。相机一定得是胶片的，胶片一定得是120的，拉开你们家冰箱，啥吃的没有，满满的全是胶卷——还必须得是过期的。&lt;/p&gt;
&lt;p&gt;　　国内景点是不能再去了，水乡古镇全是搞一夜情的，西藏全是又酸又穷除了会辞职什么都不会的城市小白领。你背包，你户外，你特立独行无所畏惧，你穿Columbia防水鞋、NorthFace冲锋衣，你用GPS迷了路，在黄山的雨夜里发出求救信息。&lt;/p&gt;
&lt;p&gt;　　你张开双手去生活去爱，你受了伤害，你的小心脏扎满绷带。你痛不欲生，你长夜痛哭过人生，痛完哭完后你顿悟你看透你蜕变，你长了一分智慧叫阅历，你多了一分气质叫成熟。你情感专家，你麻辣教师，你知性姐姐。你豆瓣粉丝几万，微博粉丝几十万，你吊了个有房有车有钱的金龟婿，然后教小姑娘们什么是爱情；你一天到晚不干正事，然后教小朋友们如何治疗拖延症；你做了个朝九晚五的无趣上班族，然后教大学生们别放弃梦想。你读书写字做主妇，你把体内毒素分泌成畅销书。你解答粉丝来信，聆听读者倾述，你款到发货，话到病除。你忙着生产一种叫“正能量”的东西，没有它，你的读者将无以为继，夜夜痛哭。&lt;/p&gt;
&lt;p&gt;　　你研习人类学、社会学、历史学、植物学、建筑学、心理学，你掌握六门外语：英语、法语、德语、日语、西班牙语、铁岭话，你知道康熙他小舅的二大爷哪年死的，你分得清古典柱式认得出欧洲广场，你叫得出路边一花一草的科属名字，你开口M2闭口流通性过剩，你和同好攒了个铅笔经济研究社，研究除了经济学以外的任何东西。&lt;/p&gt;
&lt;p&gt;　　只有门外汉才会在听古典音乐的时候想到什么画面，你谈论的是作品的母题、动机、织体、转调、升降、横向展开的层次与纵向展开的速度。你告诉还在听莫扎特“我不想不想长大”和贝多芬“当当当当”的新手：不妨尝试一下莫扎特和贝多芬的钢琴协奏曲，尤其是莫扎特的K.491和K.595，贝多芬的Op.37和Op.73，精彩绝伦，不输给他们任何的交响乐作品以及歌剧。你对中产气味古典主义模仿者勃拉姆斯充满轻视，对婆婆妈妈的柴可夫斯基只有厌烦。斯特劳斯里面只能听听理查·斯特劳斯，他的艺术歌曲还算有那么点思想性；至于约翰·斯特劳斯，天啊，真不知道这个家伙除开写了几首平庸的圆舞曲外还干了些什么。&lt;/p&gt;
&lt;p&gt;　　你上知天文下知地理，对世界充满好奇心和求知欲，没事就到网上破解谣言。你三十好几找不到对象，去非诚勿扰相亲告诉人家“喜欢TBBT加分哦”，结果“可惜不是你，陪我到最后……”。你在粉丝面前表演Name Dropping的把戏大秀才艺，隔天一觉醒来照旧要加班熬夜做苦力，供房养车还利息。&lt;/p&gt;
&lt;p&gt;　　你有知识有思想有文化有品位，唯独没有钱。你浑身上下散发着狐臭般无法抗拒的人格魅力，唯独没有活人鸟你。&lt;/p&gt;
&lt;p&gt;　　装逼尚未成功，同志仍需努力。&lt;/p&gt;
&lt;p&gt;　　你苦心智、劳筋骨、饿体肤，长夜痛哭算个屁，未曾坐过春运绿皮车者，不足以语人生。你比别人聪明你还比别人勤奋，你睡得比别人晚起得比别人早，你头发一天比一天少，肚子一天比一天大，鸡鸡一天比一天软。“吃得苦中苦，方装逼上逼”，皇天不负苦心装逼的人，你行业老大了，你商界精英了，你社会名流了，Finally, You did it, You DID it!&lt;/p&gt;
&lt;p&gt;　　你实现了“财务上的自由”。你从不像其它男人一样热衷讨论好车，一般你的做法是：买一辆。不过，好车没什么值得炫耀的，车再好能好得过煤老板的？身为“中国知识新贵”的你，更喜欢邀请朋友到家里听自己两百万的Hi-End系统上播放的马勒和布鲁克纳。你听音室里的唱片的总价能买三辆奔驰，你用十三种工具调整自己唱机唱臂的位置，你告诉朋友，玩音响最关键的不是音源，也不是音箱，而是电：水电偏冷，火电偏暖，核电偏硬，你只用来自新疆阿克苏的风电，宽松醇厚。&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;/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;</description>
    </item>
    <item>
      <title>recon-ng开源信息探测框架</title>
      <link>http://blog.leaver.me/2013/02/02/recon-ng%E5%BC%80%E6%BA%90%E4%BF%A1%E6%81%AF%E6%8E%A2%E6%B5%8B%E6%A1%86%E6%9E%B6/</link>
      <pubDate>Sat, 02 Feb 2013 06:52:28 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/02/02/recon-ng%E5%BC%80%E6%BA%90%E4%BF%A1%E6%81%AF%E6%8E%A2%E6%B5%8B%E6%A1%86%E6%9E%B6/</guid>
      <description>&lt;p&gt;作者：bystander
博客：&lt;a href=&#34;http://leaver.me&#34;&gt;http://leaver.me&lt;/a&gt;
微博：&lt;a href=&#34;http://t.qq.com/lazystander&#34;&gt;http://t.qq.com/lazystander&lt;/a&gt;
论坛：法客论坛&lt;/p&gt;
&lt;p&gt;首发。转载什么的请注明出处。起码给我留个链接啥的嘛。&lt;/p&gt;
&lt;p&gt;首先介绍一下。这个工具是国外刚刚发布的。主要用来渗透前的信息探测。使用类似Metasploit
主要有
Auxiliary：
这个模块查询主机信息泄漏页。进行hash反查，模糊名称精确，检查某个email是否密码泄漏，域名解析ip等
Contacts：
这个模块探测和某一公司有关的人员的信息，主要包括 LinkedIn 和Jigsaw 这两个模块。得到的信息可以被Auxiliary模块使用，如果和Social Engineer Toolkit(社会工程学工具集，这个工具已经发布了。是开源的。大家可以看看)，一起。效果强大。&lt;/p&gt;
&lt;p&gt;Hosts：
这个用来获取站点子域名。。包括使用baidu。Google bing等。。效果相当强大。
Output：
这个模块用来创建输出报表
Pwnedlist：
这个模块不是得shell的。他可通过 Pwnedlist.com 提供的api，如果这个网站被入侵过。那么可以直接获得其他黑客泄漏的帐号密码。。（需要去 Pwnedlist.com 注册）&lt;/p&gt;
&lt;p&gt;安装方法：
bt下直接&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;git clone https://LaNMaSteR53@bitbucket.org/LaNMaSteR53/recon-ng.git&lt;/pre&gt;
&lt;p&gt;然后有可能提示输入密码，好象是随便输一个用来保护版本控制。。我输的是toor。。
然后就安装好了。输入&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;cd recon-ng&lt;/pre&gt;
&lt;p&gt;然后&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;./recon-ng.py&lt;/pre&gt;
&lt;p&gt;首先查看有哪些模块。输入&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;modules&lt;/pre&gt;
&lt;p&gt;图一&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32339_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/88f2dd5c24ad567a09c5b6162cd60d70b3fb781d.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;我以获取子域名为例，通过我前面的介绍你已经知道了hosts模块里的所有模块基本都是干这事的。我用里面的baidu模块来说明。你也可以使用bing等，，&lt;/p&gt;
&lt;p&gt;输入命令&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;load hosts::baidu&lt;/pre&gt;
&lt;p&gt;图二&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32340_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/f818e08de804ba8875667692fbdd580ad8114667.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;刚开始你可能不清楚这个模块的说明。那么继续输入info即可查看模块的详细说明
要开始使用。我们输入&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;options&lt;/pre&gt;
&lt;p&gt;和Metasploit很像把。可以查看要使用需要的配置。&lt;/p&gt;
&lt;p&gt;图三&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32341_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/7848e773ab3e4e3ad03f59ba7b5ac6704d333ce6.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;看表，会发现有三行。第一行是标题，第二行是域名设置，第三行是输出。这个current value也就是当前值已经为true。所以不用设置。req的意思是是否必须设置。我们输入
baidu.com就是你的目标了。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;set domain baidu.com&lt;/pre&gt;
&lt;p&gt;就会从百度的结果里提取百度的子域名信息了。要开始。我们输入&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;run&lt;/pre&gt;
&lt;p&gt;图四&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32342_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/125a841869478ff39dd63113e2e9427c3ae1cf81.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;更多希望大家发掘吧。我抛砖。求引玉。&lt;/p&gt;</description>
    </item>
    <item>
      <title>C# 基础知识系列文章索引</title>
      <link>http://blog.leaver.me/2013/01/27/c%23-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0%E7%B4%A2%E5%BC%95/</link>
      <pubDate>Sun, 27 Jan 2013 20:50:08 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/27/c%23-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0%E7%B4%A2%E5%BC%95/</guid>
      <description>&lt;p&gt;清理GR的加星标项目。分享来自博客园 &lt;a href=&#34;http://www.cnblogs.com/zhili&#34;&gt;zhili&lt;/a&gt; 的C#基础系列文章。&lt;/p&gt;
&lt;p&gt;C#基础知识系列终于告了一个段落了, 本系列中主要和大家介绍了C#1.0到C# 4.0中一些重要的特性，刚开始写这个专题的初衷主要是我觉得掌握了C#这些基础知识之后，对于其他任何的一门语言都是差不多的，这样可以提高朋友们对其他语言的掌握，以及可以让大家更加迅速地掌握.NET的新特性， 并且相信这个系列对于找工作的朋友也是很有帮助的，因为很多公司面试都很看重基础知识是否扎实，是否对C#有一个全面的认识和理解，所以很多公司面试都会问到一些C#基础概念的问题，例如，经常面试会问：你是如何理解委托的，如何理解匿名函数等问题。&lt;/p&gt;
&lt;p&gt;然而这个系列中并没有介绍COM互操作性的内容以及.Net 4.5中的一些新特性，所以后面将会对这两个方面的内容进行补充，由于这个系列托的太久了(大概也有3个月吧)，所以就先告一段落的，后面将会带来.NET互操作性系列的介绍。下面就为这个系列文章做一个索引，方便大家收藏和查找。&lt;/p&gt;
&lt;p&gt;C#基础知识系列索引&lt;/p&gt;
&lt;p&gt;C#1.0&lt;/p&gt;
&lt;p&gt;1. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/10/22/Delegate.html&#34;&gt;深入解析委托——C#中为什么要引入委托&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/10/25/DeepDelegate.html&#34;&gt;委托本质论&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;3. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/10/27/MulticastDelegate.html&#34;&gt;如何用委托包装多个方法——委托链&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/10/27/Event.html&#34;&gt;事件揭秘&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;5. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/10/29/ButtonClickEvent.html&#34;&gt;当点击按钮时触发Click事件背后发生的事情&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;C# 2.0&lt;/p&gt;
&lt;p&gt;6. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/11/03/GenericType.html&#34;&gt;泛型基础篇——为什么引入泛型&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;7. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/11/08/Generic_1.html&#34;&gt;泛型深入理解(一)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;8. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/11/08/Generic_2.html&#34;&gt;泛型深入理解(二)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;9. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/11/12/GenericVari.html&#34;&gt;深入理解泛型可变性&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;10. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/11/23/Nullable.html&#34;&gt;全面解析可空类型&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;11. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/01/anonymousmethod.html&#34;&gt;匿名方法解析&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;12. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/02/Interator.html&#34;&gt;迭代器&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;C# 3.0&lt;/p&gt;
&lt;p&gt;13. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/11/basicfeatures.html&#34;&gt;全面解析对象集合初始化器、匿名类型和隐式类型&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;14. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/12/LambdaExpression.html&#34;&gt;深入理解Lambda表达式&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;15. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/17/ExtensionMethod.html&#34;&gt;全面解析扩展方法&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;16. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/12/24/Linq.html&#34;&gt;Linq介绍&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;C# 4.0&lt;/p&gt;
&lt;p&gt;17. &lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2013/01/07/DynamicType.html&#34;&gt;深入理解动态类型&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;从C#的所有特性可以看出,C#中提出的每个新特性都是建立在原来特性的基础上,并且是对原来特性的一个改进, 做这么多的改进主要是为了方便开发人员更好地使用C#来编写程序,是让我们写更少的代码来实现我们的程序,把一些额外的工作交给编译器去帮我们做,也就是很多人说微软很喜欢搞语法糖的意思(语法糖即让编译器帮我们做一些额外的事情，减少开发人员所考虑的事情，使开发人员放更多的精力放在系统的业务逻辑上面。)，大家从C# 3中提出的特性中可以很好的看出这点(指的是玩语法糖)，C#3中几乎大部分特性都是C#提供的语法糖，从CLR层面来说(指的是增加新的IL指令)，C# 3并没有更新什么，C# 4中提出的动态类型又是建立在表达式树的基础上，包括Linq也是建立在表达式树的基础上，所以每个特性都是层层递进的一个关系。相信C#后面提出的新特性将会更加方便我们开发程序，感觉所有语言的一个统一的思想都是——写更少的代码，却可以做更多的事情。但是我们不能仅仅停住于知道怎么使用它，我们还应该深入研究它的背后的故事，知道新特性是如何实现的和原理。用一句说就是——我们要知其然之气所以然，学习知识应该抱着刨根问底的态度去学习,&lt;strong&gt;相信这样的学习方式也可以让大家不感到心虚,写出的程序将会更加自信。&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>图的遍历(C#)</title>
      <link>http://blog.leaver.me/2013/01/06/%E5%9B%BE%E7%9A%84%E9%81%8D%E5%8E%86c/</link>
      <pubDate>Sun, 06 Jan 2013 16:35:45 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/06/%E5%9B%BE%E7%9A%84%E9%81%8D%E5%8E%86c/</guid>
      <description>&lt;p&gt;讲的非常好的一篇文章。感谢&lt;a href=&#34;http://www.cnblogs.com/abatei/archive/2008/06/06/1215114.html&#34;&gt;abatei&lt;/a&gt;，直接收藏分享之。&lt;/p&gt;
&lt;h2 id=&#34;图的存储结构&#34;&gt;图的存储结构&lt;/h2&gt;
&lt;p&gt;图的存储结构除了要存储图中各个顶点的本身的信息外，同时还要存储顶点与顶点之间的所有关系（边的信息），因此，图的结构比较复杂，很难以数据元素在存储区中的物理位置来表示元素之间的关系，但也正是由于其任意的特性，故物理表示方法很多。常用的图的存储结构有邻接矩阵、邻接表、十字链表和邻接多重表。&lt;/p&gt;
&lt;h3 id=&#34;821邻接矩阵表示法&#34;&gt;8.2.1  邻接矩阵表示法&lt;/h3&gt;
&lt;p&gt;对于一个具有n个顶点的图，可以使用n*n的矩阵（二维数组）来表示它们间的邻接关系。图8.10和图8.11中，矩阵A(i，j)=1表示图中存在一条边(V&lt;sub&gt;i&lt;/sub&gt;，V&lt;sub&gt;j&lt;/sub&gt;)，而A(i，j)=0表示图中不存在边(V&lt;sub&gt;i&lt;/sub&gt;，V&lt;sub&gt;j&lt;/sub&gt;)。实际编程时，当图为不带权图时，可以在二维数组中存放bool值，A(i，j)=true表示存在边(V&lt;sub&gt;i&lt;/sub&gt;，V&lt;sub&gt;j&lt;/sub&gt;)，A(i，j)=false表示不存在边(V&lt;sub&gt;i&lt;/sub&gt;，V&lt;sub&gt;j&lt;/sub&gt;)；当图带权值时，则可以直接在二维数组中存放权值，A(i，j)=null表示不存在边(V&lt;sub&gt;i&lt;/sub&gt;，V&lt;sub&gt;j&lt;/sub&gt;)。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/31196_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/34232ee6d725c72cdc277e3b5146680671171e7f.jpg&#34;&gt;&lt;/a&gt;
图8.10所示的是无向图的邻接矩阵表示法，可以观察到，矩阵延对角线对称，即A(i，j)= A(j，i)。无向图邻接矩阵的第i行或第i列非零元素的个数其实就是第i个顶点的度。这表示无向图邻接矩阵存在一定的数据冗余。&lt;/p&gt;
&lt;p&gt;图8.11所示的是有向图邻接矩阵表示法，矩阵并不延对角线对称，A(i，j)=1表示顶点V&lt;sub&gt;i&lt;/sub&gt;邻接到顶点V&lt;sub&gt;j&lt;/sub&gt;；A(j，i)=1则表示顶点V&lt;sub&gt;i&lt;/sub&gt;邻接自顶点V&lt;sub&gt;j&lt;/sub&gt;。两者并不象无向图邻接矩阵那样表示相同的意思。有向图邻接矩阵的第i行非零元素的个数其实就是第i个顶点的出度，而第i列非零元素的个数是第i个顶点的入度，即第i个顶点的度是第i行和第i列非零元素个数之和。&lt;/p&gt;
&lt;p&gt;由于存在n个顶点的图需要n&lt;sup&gt;2&lt;/sup&gt;个数组元素进行存储，当图为稀疏图时，使用邻接矩阵存储方法将出现大量零元素，照成极大地空间浪费，这时应该使用邻接表表示法存储图中的数据。&lt;/p&gt;
&lt;h3 id=&#34;822邻接表表示法&#34;&gt;8.2.2 邻接表表示法&lt;/h3&gt;
&lt;p&gt;图的邻接矩阵存储方法跟树的孩子链表示法相类似，是一种顺序分配和链式分配相结合的存储结构。邻接表由表头结点和表结点两部分组成，其中图中每个顶点均对应一个存储在数组中的表头结点。如这个表头结点所对应的顶点存在相邻顶点，则把相邻顶点依次存放于表头结点所指向的单向链表中。如图8.12所示，表结点存放的是邻接顶点在数组中的索引。对于无向图来说，使用邻接表进行存储也会出现数据冗余，表头结点A所指链表中存在一个指向C的表结点的同时，表头结点C所指链表也会存在一个指向A的表结点。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/31197_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/e6366b11df17b7aee6ddd118de3c84bb1c760c37.jpg&#34;&gt;&lt;/a&gt;
有向图的邻接表有出边表和入边表（又称逆邻接表）之分。出边表的表结点存放的是从表头结点出发的有向边所指的尾顶点；入边表的表结点存放的则是指向表头结点的某个头顶点。如图8.13所示，图(b)和(c)分别为有向图(a)的出边表和入边表。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/31198_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/847e7b120ab02fcb88556adaa762a4098e7ba831.jpg&#34;&gt;&lt;/a&gt;
以上所讨论的邻接表所表示的都是不带权的图，如果要表示带权图，可以在表结点中增加一个存放权的字段，其效果如图8.14所示。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/31199_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/a78cf3f8419a98ca2cede25716595c14a30ae2d3.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;【注意】：观察图8.14可以发现，当删除存储表头结点的数组中的某一元素，有可能使部分表头结点索引号的改变，从而导致大面积修改表结点的情况发生。可以在表结点中直接存放指向表头结点的指针以解决这个问题（在链表中存放类实例即是存放指针，但必须要保证表头结点是类而不是结构体）。在实际创建邻接表时，甚至可以使用链表代替数组存放表头结点或使用顺序表存代替链表存放表结点。对所学的数据结构知识应当根据实际情况及所使用语言的特点灵活应用，切不可生搬硬套。&lt;/p&gt;
&lt;p&gt;【例8-1  AdjacencyList.cs】图的邻接表存储结构&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;using System;
using System.Collections.Generic;
public class AdjacencyList&amp;lt;T&amp;gt;
{
    List&amp;lt;Vertex&amp;lt;T&amp;gt;&amp;gt; items; //图的顶点集合
    public AdjacencyList() : this(10) { } //构造方法
    public AdjacencyList(int capacity) //指定容量的构造方法
    {
        items = new List&amp;lt;Vertex&amp;lt;T&amp;gt;&amp;gt;(capacity);
    }
    public void AddVertex(T item) //添加一个顶点
    {   //不允许插入重复值
        if (Contains(item))
        {
            throw new ArgumentException(&#34;插入了重复顶点！&#34;);
        }
        items.Add(new Vertex&amp;lt;T&amp;gt;(item));
    }
    public void AddEdge(T from, T to) //添加无向边
    {
        Vertex&amp;lt;T&amp;gt; fromVer = Find(from); //找到起始顶点
        if (fromVer == null)
        {
            throw new ArgumentException(&#34;头顶点并不存在！&#34;);
        }
        Vertex&amp;lt;T&amp;gt; toVer = Find(to); //找到结束顶点
        if (toVer == null)
        {
            throw new ArgumentException(&#34;尾顶点并不存在！&#34;);
        }
        //无向边的两个顶点都需记录边信息
        AddDirectedEdge(fromVer, toVer);
        AddDirectedEdge(toVer, fromVer);
    }
    public bool Contains(T item) //查找图中是否包含某项
    {
        foreach (Vertex&amp;lt;T&amp;gt; v in items)
        {
            if (v.data.Equals(item))
            {
                return true;
            }
        }
        return false;
    }
    private Vertex&amp;lt;T&amp;gt; Find(T item) //查找指定项并返回
    {
        foreach (Vertex&amp;lt;T&amp;gt; v in items)
        {
            if (v.data.Equals(item))
            {
                return v;
            }
        }
        return null;
    }
    //添加有向边
    private void AddDirectedEdge(Vertex&amp;lt;T&amp;gt; fromVer, Vertex&amp;lt;T&amp;gt; toVer)
    {
        if (fromVer.firstEdge == null) //无邻接点时
        {
            fromVer.firstEdge = new Node(toVer);
        }
        else
        {
            Node tmp, node = fromVer.firstEdge;
            do
            {   //检查是否添加了重复边
                if (node.adjvex.data.Equals(toVer.data))
                {
                    throw new ArgumentException(&#34;添加了重复的边！&#34;);
                }
                tmp = node;
                node = node.next;
            } while (node != null);
            tmp.next = new Node(toVer); //添加到链表未尾
        }
    }
    public override string ToString() //仅用于测试
    {   //打印每个节点和它的邻接点
        string s = string.Empty;
        foreach (Vertex&amp;lt;T&amp;gt; v in items)
        {
            s += v.data.ToString() + &#34;:&#34;;
            if (v.firstEdge != null)
            {
                Node tmp = v.firstEdge;
                while (tmp != null)
                {
                    s += tmp.adjvex.data.ToString();
                    tmp = tmp.next;
                }
            }
            s += &#34;\r\n&#34;;
        }
        return s;
    }
    //嵌套类，表示链表中的表结点
    public class Node
    {
        public Vertex&amp;lt;T&amp;gt; adjvex; //邻接点域
        public Node next; //下一个邻接点指针域
        public Node(Vertex&amp;lt;T&amp;gt; value)
        {
            adjvex = value;
        }
    }
    //嵌套类，表示存放于数组中的表头结点
    public class Vertex&amp;lt;TValue&amp;gt;
    {
        public TValue data; //数据
        public Node firstEdge; //邻接点链表头指针
        public Boolean visited; //访问标志,遍历时使用
        public Vertex(TValue value) //构造方法
        {
            data = value;
        }
    }
}&lt;/pre&gt;
&lt;/div&gt;
AdjacencyList&amp;lt;T&amp;gt;类使用泛型实现了图的邻接表存储结构。它包含两个内部类，Vertex&amp;lt;Tvalue&amp;gt;类（109～118行代码）用于表示一个表头结点，Node类（99～107）则用于表示表结点，其中存放着邻接点信息，用来表示表头结点的某条边。多个Node用next指针相连形成一个单链表，表头指针为Vertex类的firstEdge成员，表头结点所代表的顶点的所有边的信息均包含在链表内，其结构如图8.12所示。所不同之处在于：
&lt;p&gt;l         Vertex类中包含了一个visited成员，它的作用是在图遍历时标识当前节点是否被访问过，这一点在稍后会讲到。&lt;/p&gt;</description>
    </item>
    <item>
      <title>从相亲延伸出的婚恋意义</title>
      <link>http://blog.leaver.me/2012/12/10/%E4%BB%8E%E7%9B%B8%E4%BA%B2%E5%BB%B6%E4%BC%B8%E5%87%BA%E7%9A%84%E5%A9%9A%E6%81%8B%E6%84%8F%E4%B9%89/</link>
      <pubDate>Mon, 10 Dec 2012 17:45:16 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/12/10/%E4%BB%8E%E7%9B%B8%E4%BA%B2%E5%BB%B6%E4%BC%B8%E5%87%BA%E7%9A%84%E5%A9%9A%E6%81%8B%E6%84%8F%E4%B9%89/</guid>
      <description>&lt;p&gt;相亲现在挺火的。。&lt;/p&gt;
&lt;p&gt;文章来自&lt;strong&gt;xiuloveshow&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;/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;</description>
    </item>
    <item>
      <title>从平庸到幸福</title>
      <link>http://blog.leaver.me/2012/12/05/%E4%BB%8E%E5%B9%B3%E5%BA%B8%E5%88%B0%E5%B9%B8%E7%A6%8F/</link>
      <pubDate>Wed, 05 Dec 2012 08:05:58 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/12/05/%E4%BB%8E%E5%B9%B3%E5%BA%B8%E5%88%B0%E5%B9%B8%E7%A6%8F/</guid>
      <description>&lt;p&gt;一篇来自左岸的文章，可以读一读。只是不知道有几人能够认认真真读完。文予有缘人。随意吧。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;作者：&lt;a href=&#34;http://www.zreading.cn/archives/3030.html&#34;&gt;文刀&lt;/a&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;/p&gt;</description>
    </item>
    <item>
      <title>关于爱情和爱情的附加值</title>
      <link>http://blog.leaver.me/2012/10/20/%E5%85%B3%E4%BA%8E%E7%88%B1%E6%83%85%E5%92%8C%E7%88%B1%E6%83%85%E7%9A%84%E9%99%84%E5%8A%A0%E5%80%BC/</link>
      <pubDate>Sat, 20 Oct 2012 14:44:32 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/20/%E5%85%B3%E4%BA%8E%E7%88%B1%E6%83%85%E5%92%8C%E7%88%B1%E6%83%85%E7%9A%84%E9%99%84%E5%8A%A0%E5%80%BC/</guid>
      <description>&lt;p&gt;　　看到一篇好文。出处未找到。分享之。如果你不能静下来看完。那么就看我画出来的部分吧。&lt;/p&gt;
&lt;p&gt;　　我一直在想，假如查尔斯王子只是一个普通的男人，那么19岁的戴安娜还会在明知他另有所爱的情况下嫁给他吗？在戴安娜一段被公开的录音带中，她曾经说大婚那天是她生命中最糟糕的一天——“我的心像死一样平静，我感觉自己像待宰的羔羊。”&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;blockquote&gt;
&lt;p&gt;但是对于我们寻常女子来说，我们能做得到吗？喜欢上一个男人，就跟他欢天喜地？我相信许多人是做不到的，因为我们对爱情的指望太多，我们期待从爱情中得到“附加值。我们对自己说，世上没有无缘无故的爱，如果爱一个人，不能给自己带来提升，为什么要爱他呢？甚至有许许多多的爱情指南大大方方地告诉我们：干得好不如嫁得好，为什么不能一举两得？嫁一个优秀的男人，既得到爱情又得到财富。是呀，为什么不呢？问题是世界上哪里有那么多便宜事？即使美丽如戴安娜王妃都无法如愿，何况我们呢？&lt;/p&gt;
&lt;/blockquote&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;blockquote&gt;
&lt;p&gt;出生于法国的英国作家毛姆曾经说过：“感情有理智所根本不能理解的理由。”他在传世之作《月亮和六便士》（卓越 当当 京东）中描写了一个名叫爱施略夫的男人，那是一个从任何一个角度讲都称得上是“好丈夫”的男人。他有钱，给妻子提供了安逸的生活，他对妻子很好，什么事情都由着她的心思。而她的妻子对他也一直很不错，直到有一天，他的妻子遇到一名穷困潦倒生活不能自理的画家。这名画家的原型据说是高更。人们都谴责这名画家勾引了这名良家妇女，但是毛姆另有解释，原话摘录如下：“过去我认为她爱施特略夫，实际上只是男人的爱抚和生活的安适在女人身上引起的自然反应。大多数女人都把这种反应当爱情了。这是一种对任何一个人都可能产生的被动的感情，正像藤蔓可以攀附在随便哪株树上一样。因为这种感情可以叫一个女孩子嫁给任何一个需要她的男人，相信日久天长便会对这个人产生爱情，所以世俗的见解便断定了它的力量。但是说到底，这种感情是什么呢？它只不过是对有保障的生活的满足，对拥有家资的骄傲，对有人需要自己沾沾自喜，和对建立起自己的家庭洋洋得意而已。女人们秉性善良、喜爱虚荣，因此便认为这种感情极富于精神价值。但是在冲动的热情面前，这种感情是毫无防卫能力的。”&lt;/p&gt;
&lt;/blockquote&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;blockquote&gt;
&lt;p&gt;一个你不爱的男人，即使一切都好，又能好到哪里去呢？无非是他能给一些你现在还得不到的生活品质，但是如果你对自己有信心，那些所谓的生活品质是很难达到的吗？也许现在你会为一个肯送你路易威登手提袋的男人而心动，但是当你自己可以到巴黎总店随便挑选的时候，你还会为那个男人心动吗？你还会因为他送得起这样一个昂贵的包而凭空给他打几个高分吗？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;世间值得追求的东西很多，但惟有爱情，是必须真心相爱才可以尝到它的滋味的。而其他的东西，你得到它的途径其实有很多，并不一定非要通过和一个人结婚才可以得到。既然这样，你为什么要给自己的爱设定那么高的门槛？我担心的不是你对爱的要求太高，我是担心迈得进你门槛的人，恰恰都是与爱无关的人。因为真爱是不需要门槛的，而且也不屑于门槛。爱是两情相悦，你情我愿，又不是在自由市场挑西红柿，非要找性能价格，比最合理的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;　　恋人之间最爱问的一句话，大概就是“你爱我什么？”从来没有人会说我爱你的钱，你的财富，你所能给我提供的生活，为什么？因为我们都知道那太煞风景。至今为止，我听到的最动人的答案是一句英文：“I LOVE YOU NOT BECAUSE OF WHO YOU ARE，BUT BECAUSE OF WHO I AM WHEN I AM WITH YOU.”我不知道如何把它翻译得浪漫多情，但是我想即使是直截了当的翻译，那其中的真情也足以动人：我爱你，并不是因为你是谁，而是因为和你在一起时，我才是最真实的我。&lt;/p&gt;
&lt;p&gt;[text]PS:私自觉得那句英文应该翻译为：我爱你，不是因为你是谁，而是因为我在你面前可以是谁。[/text]&lt;/p&gt;</description>
    </item>
    <item>
      <title>C# 网络编程系列</title>
      <link>http://blog.leaver.me/2012/09/25/c%23-%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E7%B3%BB%E5%88%97/</link>
      <pubDate>Tue, 25 Sep 2012 18:04:21 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/25/c%23-%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E7%B3%BB%E5%88%97/</guid>
      <description>&lt;p&gt;本系列来自博客园的&lt;a href=&#34;http://www.cnblogs.com/zhili/&#34;&gt;Learning hard&lt;/a&gt;园友。每个博主都不容易，我这里只是给出一个索引，希望更多热爱技术的人能够看到。给分享者更多的鼓励和支持。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/08/11/NetWorkProgramming.html&#34;&gt;专题一：网络协议简介&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/08/18/HTTP.html&#34;&gt;专题二：HTTP协议详解&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/08/23/WebServer.html&#34;&gt;专题三：自定义Web服务器&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/08/24/WebBrowser.html&#34;&gt;专题四：自定义Web浏览器&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/08/25/TCP.html&#34;&gt;专题五：TCP编程&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/09/01/UDP_Multicast.html&#34;&gt;专题六：UDP编程&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/09/03/UDPBroadcas.html&#34;&gt;专题七：UDP编程补充——UDP广播程序的实现&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/09/14/P2P_PNPR.html&#34;&gt;专题八：P2P编程&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/09/23/QQ_P2P.html&#34;&gt;专题九：实现类似QQ的即时通信程序&lt;/a&gt;
&lt;a href=&#34;http://www.cnblogs.com/zhili/archive/2012/09/24/MailSend_POP3_SMTP.html&#34;&gt;专题十：实现简单的邮件收发器&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>WPF毛玻璃效果Demo和一个问题</title>
      <link>http://blog.leaver.me/2012/09/24/wpf%E6%AF%9B%E7%8E%BB%E7%92%83%E6%95%88%E6%9E%9Cdemo%E5%92%8C%E4%B8%80%E4%B8%AA%E9%97%AE%E9%A2%98/</link>
      <pubDate>Mon, 24 Sep 2012 08:04:25 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/24/wpf%E6%AF%9B%E7%8E%BB%E7%92%83%E6%95%88%E6%9E%9Cdemo%E5%92%8C%E4%B8%80%E4%B8%AA%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;p&gt;　　那天看到WPF书上讲的毛玻璃效果，就去找了下效果。。忘了例子是从哪发现得了。。先看下效果，&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27420_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/638a69761205e3d5c16a5bd34a2f775de190d137.jpg&#34; title=&#34;glass&#34;&gt;&lt;/a&gt;
　　但是这不是重点，作者给出的代码有一个设计时错误。。错误提示为：
无法将类型为“Microsoft.Expression.Platform.WPF.InstanceBuilders.WindowInstance”的对象强制转换为类型“System.Windows.Window”，，&lt;/p&gt;
&lt;p&gt;　　中文搜了一下。没有发现有人解决过。目测。。。然后又拿英文搜了下。几经辗转。。终于是解决了。。原文在&lt;a href=&#34;http://social.msdn.microsoft.com/Forums/is/wpf/thread/931e75a8-cab6-492d-89cd-b7ca291fa273&#34;&gt;Unable to cast XAML error&lt;/a&gt;。其实就是将原作者这个函数修改如下的&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;public static void OnIsEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {

            if ((bool)args.NewValue == true)
            {
                Window wnd = obj as Window;
                if (wnd != null) wnd.Loaded += new RoutedEventHandler(wnd_Loaded);
            }
        }&lt;/pre&gt; 
&lt;p&gt;　　也就是验证了一下转换是否成功。&lt;/p&gt;
&lt;p&gt;下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=61615&amp;amp;uk=1493685990&#34;&gt;修改后的RGSamples&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>一个可定制的WPF任务对话框</title>
      <link>http://blog.leaver.me/2012/09/24/%E4%B8%80%E4%B8%AA%E5%8F%AF%E5%AE%9A%E5%88%B6%E7%9A%84wpf%E4%BB%BB%E5%8A%A1%E5%AF%B9%E8%AF%9D%E6%A1%86/</link>
      <pubDate>Mon, 24 Sep 2012 08:03:17 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/24/%E4%B8%80%E4%B8%AA%E5%8F%AF%E5%AE%9A%E5%88%B6%E7%9A%84wpf%E4%BB%BB%E5%8A%A1%E5%AF%B9%E8%AF%9D%E6%A1%86/</guid>
      <description>&lt;p&gt;今天实在看WPF揭秘的时候看到TaskDialog这个控件的。然后就去找了一下开源的代码。在codeproject上发现了这个，非常给力。。另外codeproject改版后很漂亮哦。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27400_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ea5f46934b5478701eb79bb9b9b08381704b7996.jpg&#34; title=&#34;one&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;介绍&#34;&gt;介绍：&lt;/h3&gt;
&lt;p&gt;这是用WPF实现Vista上TaskDialog效果的代码。&lt;/p&gt;
&lt;h3 id=&#34;messagbox消息框&#34;&gt;Messagbox消息框&lt;/h3&gt;
&lt;p&gt;通过调用重写的静态Show方法。TaskDialog就会表现的像一个Messagebox。他有四个文本类型的属性：Header（头部）, Content（内容）, Detail（更多）, 和 Footer（底部），其实Detail是一个折叠的区域， 而Header和Footer还有一个icon属性（HeaderIcon和FooterIcon），除此之外，Header还有Background（背景）和Foreground（前景）属性&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;// TaskDialog.Show方法签名
public static TaskDialogResult Show(
    string title, 
    string header, 
    string content, 
    string detail, 
    string footer, 
    TaskDialogButton button, 
    TaskDialogResult defaultResult, 
    TaskDialogIcon headerIcon, 
    TaskDialogIcon footerIcon, 
    Brush headerBackground, 
    Brush headerForeground)

// TaskDialog.Show 方法的一个例子
TaskDialog.Show(&#34;Task Dialog 测试&#34;,
     &#34;消息框的标题文字&#34;,
     &#34;消息框的内容部分. &#34; +
     &#34; 可以自适应内容.&#34;,
     &#34;消息框的细节部分 &#34; +
     &#34;可以自适应内容&#34;,
     &#34;消息框的底部.&#34;,
     TaskDialogButton.Ok,
     TaskDialogResult.None,
     TaskDialogIcon.Information,
     TaskDialogIcon.Shield,
     Brushes.White,
     Brushes.Navy);&lt;/pre&gt; 
&lt;h3 id=&#34;定制taskdialog&#34;&gt;定制TaskDialog&lt;/h3&gt;
&lt;p&gt;使用静态的Show方法。Header, Content, Detail, 和Footer 就限制了只能传递字符串作为值了。
为了定义这个对话框，你先创建TaskDialog类的一个对象，然后分别设置一下各个属性，最后调用Show方法就可以了&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;// TaskDialog 实例化例子
TaskDialog dialog = new TaskDialog();
dialog.title: = &#34;TaskDialog example&#34;;
dialog.HeaderIcon = TaskDialogIcon.Warning;
dialog.SystemSound = TaskDialogSound.Exclamation;
// header 属性设置
dialog.Header = &#34;This is the Header.&#34;;
dialog.HeaderBackground = Brushes.DarkGray;
dialog.HeaderForeground = Brushes.White;
// Content, Detail 和 Footer属性设置
dialog.Content = &#34;This is the content&#34;;
dialog.Detail = &#34;This is the detail&#34;;
dialog.Footer = &#34;this is the Footer&#34;;
dialog.Show();&lt;/pre&gt; 
&lt;p&gt;TaskDialog控件派生自HeaderedContentControl类，因为从HeaderedContentControl类可以获得Header和Content属性，TaskDialog仅仅是添加了Detail和Footer属性，这些属性是Object类型，并且有他们自己的template（模板）属性HeaderTemplate, ContentTemplate, DetailTemplate, 和 FooterTemplate)，TaskDialog类对于文本内容有着缺省的数据模板，当然你也可以用那四个模板来替换，这样你就可以以你喜欢的任何方式来格式化文本了。下面这个图展示了通过斜体和下划线来格式化文本。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27401_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/05a7c6d00f37749a2b770d0b1f1ebaab51528de0.jpg&#34; title=&#34;two&#34;&gt;&lt;/a&gt;
图2&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;//为上面这个图的content属性的 DataTemplate 模板 
&amp;lt;DataTemplate x:Key=&#34;_customContentDataTemplate&#34;&amp;gt;
   &amp;lt;TextBlock Text=&#34;{Binding Content, 
        RelativeSource={RelativeSource FindAncestor, 
                        AncestorType={x:Type Controls:TaskDialog}}}&#34; 
        FontStyle=&#34;Italic&#34; 
        TextDecorations=&#34;Underline&#34; 
        TextWrapping=&#34;Wrap&#34;/&amp;gt;
&amp;lt;/DataTemplate&amp;gt;&lt;/pre&gt; 
&lt;p&gt;因为Header，Content，Detail和Footer是object类型，因此不再受到只能是文本的限制了，你可以防止你喜欢的任何类型到TaskDialog，下面这个例子中的TaskDialog是不是很像UAC的提示呢。这里Content属性是一个UserControl类型，放置了一个图片和一些文本还有两个CommandButtons（都是普通的按钮。。不过添加了一些定制的样式，再加了Header属性）&lt;/p&gt;</description>
    </item>
    <item>
      <title>汇编-32位CPU所含有的寄存器</title>
      <link>http://blog.leaver.me/2012/09/24/%E6%B1%87%E7%BC%96-32%E4%BD%8Dcpu%E6%89%80%E5%90%AB%E6%9C%89%E7%9A%84%E5%AF%84%E5%AD%98%E5%99%A8/</link>
      <pubDate>Mon, 24 Sep 2012 08:02:36 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/24/%E6%B1%87%E7%BC%96-32%E4%BD%8Dcpu%E6%89%80%E5%90%AB%E6%9C%89%E7%9A%84%E5%AF%84%E5%AD%98%E5%99%A8/</guid>
      <description>&lt;p&gt;今年的课程有汇编。真为校领导的智商捉鸡。。不过还是要学的。分享一篇来自&lt;a href=&#34;http://blog.minidx.com/2007/12/10/233.html&#34;&gt;中文FLEX例子&lt;/a&gt;的汇编寄存器的文章。很不错的一篇寄存器详解的文章。文章最后是我找到的一个汇编指令助手。&lt;/p&gt;
&lt;p&gt;　　4个数据寄存器(EAX、EBX、ECX和EDX)　　
　　2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP)
　　6个段寄存器(ES、CS、SS、DS、FS和GS)
　　1个指令指针寄存器(EIP) 1个标志寄存器(EFlags)&lt;/p&gt;
&lt;h3 id=&#34;1数据寄存器&#34;&gt;1、数据寄存器&lt;/h3&gt;
&lt;p&gt;　　数据寄存器主要用来保存操作数和运算结果等信息，从而节省读取操作数所需占用总线和访问存储器的时间。32位CPU有4个32位的通用寄存器EAX、EBX、ECX和EDX。对低16位数据的存取，不会影响高16位的数据。这些低16位寄存器分别命名为：AX、BX、CX和DX，它和先前的CPU中的寄存器相一致。&lt;/p&gt;
&lt;p&gt;　　4个16位寄存器又可分割成8个独立的8位寄存器(AX：AH-AL、BX：BH-BL、CX：CH-CL、DX：DH-DL)，每个寄存器都有自己的名称，可独立存取。程序员可利用数据寄存器的这种”可分可合”的特性，灵活地处理字/字节的信息。&lt;/p&gt;
&lt;p&gt;　　寄存器AX和AL通常称为累加器(Accumulator)，用累加器进行的操作可能需要更少时间。累加器可用于乘、 除、输入/输出等操作，它们的使用频率很高； 寄存器BX称为基地址寄存器(Base Register)。它可作为存储器指针来使用； 寄存器CX称为计数寄存器(Count Register)。在循环和字符串操作时，要用它来控制循环次数；在位操作 中，当移多位时，要用CL来指明移位的位数；&lt;/p&gt;
&lt;p&gt;　　寄存器DX称为数据寄存器(Data Register)。在进行乘、除运算时，它可作为默认的操作数参与运算，也 可用于存放I/O的端口地址。在16位CPU中，AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址，但在32位CPU中，其32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果，而且也可作为指针寄存器，所以，这些32位寄存器更具有通用性。&lt;/p&gt;
&lt;h3 id=&#34;2变址寄存器&#34;&gt;2、变址寄存器&lt;/h3&gt;
&lt;p&gt;　　32位CPU有2个32位通用寄存器ESI和EDI。其低16位对应先前CPU中的SI和DI，对低16位数据的存取，不影响高16位的数据。&lt;/p&gt;
&lt;p&gt;　　寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register)，它们主要用于存放存储单元在段内的偏移量，用它们可实现多种存储器操作数的寻址方式，为以不同的地址形式访问存储单元提供方便。变址寄存器不可分割成8位寄存器。作为通用寄存器，也可存储算术逻辑运算的操作数和运算结果。它们可作一般的存储器指针使用。在字符串操作指令的执行过程中，对它们有特定的要求，而且还具有特殊的功能。&lt;/p&gt;
&lt;h3 id=&#34;3指针寄存器&#34;&gt;3、指针寄存器&lt;/h3&gt;
&lt;p&gt;　　32位CPU有2个32位通用寄存器EBP和ESP。其低16位对应先前CPU中的SBP和SP，对低16位数据的存取，不影响高16位的数据。&lt;/p&gt;
&lt;p&gt;　　寄存器EBP、ESP、BP和SP称为指针寄存器(Pointer Register)，主要用于存放堆栈内存储单元的偏移量，用它们可实现多种存储器操作数的寻址方式，为以不同的地址形式访问存储单元提供方便。指针寄存器不可分割成8位寄存器。作为通用寄存器，也可存储算术逻辑运算的操作数和运算结果。&lt;/p&gt;
&lt;p&gt;　　它们主要用于访问堆栈内的存储单元，并且规定：&lt;/p&gt;
&lt;p&gt;　　BP为基指针(Base Pointer)寄存器，用它可直接存取堆栈中的数据；&lt;/p&gt;
&lt;p&gt;　　SP为堆栈指针(Stack Pointer)寄存器，用它只可访问栈顶。&lt;/p&gt;
&lt;h3 id=&#34;4段寄存器&#34;&gt;4、段寄存器&lt;/h3&gt;
&lt;p&gt;　　段寄存器是根据内存分段的管理模式而设置的。内存单元的物理地址由段寄存器的值和一个偏移量组合而成&lt;/p&gt;
&lt;p&gt;　　的，这样可用两个较少位数的值组合成一个可访问较大物理空间的内存地址。&lt;/p&gt;
&lt;p&gt;　　CPU内部的段寄存器：&lt;/p&gt;
&lt;p&gt;　　CS——代码段寄存器(Code Segment Register)，其值为代码段的段值；
　　DS——数据段寄存器(Data Segment Register)，其值为数据段的段值；　
　　ES——附加段寄存器(Extra Segment Register)，其值为附加数据段的段值；
　　SS——堆栈段寄存器(Stack Segment Register)，其值为堆栈段的段值；
　　FS——附加段寄存器(Extra Segment Register)，其值为附加数据段的段值；
　　GS——附加段寄存器(Extra Segment Register)，其值为附加数据段的段值。&lt;/p&gt;
&lt;p&gt;　　在16位CPU系统中，它只有4个段寄存器，所以，程序在任何时刻至多有4个正在使用的段可直接访问；在32位微机系统中，它有6个段寄存器，所以，在此环境下开发的程序最多可同时访问6个段。32位CPU有两个不同的工作方式：实方式和保护方式。在每种方式下，段寄存器的作用是不同的。有关规定简单描述如下：&lt;/p&gt;
&lt;p&gt;　　实方式： 前4个段寄存器CS、DS、ES和SS与先前CPU中的所对应的段寄存器的含义完全一致，内存单元的逻辑地址仍为”段值：偏移量”的形式。为访问某内存段内的数据，必须使用该段寄存器和存储单元的偏移量。&lt;/p&gt;
&lt;p&gt;　　保护方式： 在此方式下，情况要复杂得多，装入段寄存器的不再是段值，而是称为”选择子”(Selector)的某个值。&lt;/p&gt;
&lt;h3 id=&#34;5指令指针寄存器&#34;&gt;5、指令指针寄存器&lt;/h3&gt;
&lt;p&gt;　　32位CPU把指令指针扩展到32位，并记作EIP，EIP的低16位与先前CPU中的IP作用相同。&lt;/p&gt;
&lt;p&gt;　　指令指针EIP、IP(Instruction Pointer)是存放下次将要执行的指令在代码段的偏移量。在具有预取指令功能的系统中，下次要执行的指令通常已被预取到指令队列中，除非发生转移情况。所以，在理解它们的功能时，不考虑存在指令队列的情况。&lt;/p&gt;
&lt;p&gt;　　在实方式下，由于每个段的最大范围为64K，所以，EIP中的高16位肯定都为0，此时，相当于只用其低16位的IP来反映程序中指令的执行次序。&lt;/p&gt;
&lt;h3 id=&#34;6标志寄存器&#34;&gt;6、标志寄存器&lt;/h3&gt;
&lt;p&gt;　　一、运算结果标志位&lt;/p&gt;
&lt;p&gt;　　1、进位标志CF(Carry Flag)&lt;/p&gt;
&lt;p&gt;　　进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位，那么，其值为1，否则其值为0。使用该标志位的情况有：多字(字节)数的加减运算，无符号数的大小比较运算，移位操作，字(字节)之间移位，专门改变CF值的指令等。&lt;/p&gt;
&lt;p&gt;　　2、奇偶标志PF(Parity Flag)&lt;/p&gt;
&lt;p&gt;　　奇偶标志PF用于反映运算结果中”1″的个数的奇偶性。如果”1″的个数为偶数，则PF的值为1，否则其值为0。&lt;/p&gt;
&lt;p&gt;　　利用PF可进行奇偶校验检查，或产生奇偶校验位。在数据传送过程中，为了提供传送的可靠性，如果采用奇偶校验的方法，就可使用该标志位。&lt;/p&gt;
&lt;p&gt;　　3、辅助进位标志AF(Auxiliary Carry Flag)&lt;/p&gt;
&lt;p&gt;　　在发生下列情况时，辅助进位标志AF的值被置为1，否则其值为0：&lt;/p&gt;
&lt;p&gt;　　(1)、在字操作时，发生低字节向高字节进位或借位时；　　
　　(2)、在字节操作时，发生低4位向高4位进位或借位时。&lt;/p&gt;
&lt;p&gt;　　对以上6个运算结果标志位，在一般编程情况下，标志位CF、ZF、SF和OF的使用频率较高，而标志位PF和AF的使用频率较低。&lt;/p&gt;
&lt;p&gt;　　4、零标志ZF(Zero Flag)&lt;/p&gt;
&lt;p&gt;　　零标志ZF用来反映运算结果是否为0。如果运算结果为0，则其值为1，否则其值为0。在判断运算结果是否为0时，可使用此标志位。&lt;/p&gt;
&lt;p&gt;　　5、符号标志SF(Sign Flag)&lt;/p&gt;
&lt;p&gt;　　符号标志SF用来反映运算结果的符号位，它与运算结果的最高位相同。在微机系统中，有符号数采用补码表示法，所以，SF也就反映运算结果的正负号。运算结果为正数时，SF的值为0，否则其值为1。&lt;/p&gt;
&lt;p&gt;　　6、溢出标志OF(Overflow Flag)&lt;/p&gt;
&lt;p&gt;　　溢出标志OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围，则称为溢出，OF的值被置为1，否则，OF的值被清为0。”溢出”和”进位”是两个不同含义的概念，不要混淆。如果不太清楚的话，请查阅《计算机组成原理》课程中的有关章节。&lt;/p&gt;
&lt;p&gt;　　二、状态控制标志位&lt;/p&gt;
&lt;p&gt;　　状态控制标志位是用来控制CPU操作的，它们要通过专门的指令才能使之发生改变。&lt;/p&gt;
&lt;p&gt;　　1、追踪标志TF(Trap Flag)&lt;/p&gt;
&lt;p&gt;　　当追踪标志TF被置为1时，CPU进入单步执行方式，即每执行一条指令，产生一个单步中断请求。这种方式主要用于程序的调试。指令系统中没有专门的指令来改变标志位TF的值，但程序员可用其它办法来改变其值。&lt;/p&gt;
&lt;p&gt;　　2、中断允许标志IF(Interrupt-enable Flag)&lt;/p&gt;
&lt;p&gt;　　中断允许标志IF是用来决定CPU是否响应CPU外部的可屏蔽中断发出的中断请求。但不管该标志为何值，CPU都必须响应CPU外部的不可屏蔽中断所发出的中断请求，以及CPU内部产生的中断请求。具体规定如下：&lt;/p&gt;
&lt;p&gt;　　(1)、当IF=1时，CPU可以响应CPU外部的可屏蔽中断发出的中断请求；
　　(2)、当IF=0时，CPU不响应CPU外部的可屏蔽中断发出的中断请求。&lt;/p&gt;
&lt;p&gt;　　CPU的指令系统中也有专门的指令来改变标志位IF的值。&lt;/p&gt;
&lt;p&gt;　　3、方向标志DF(Direction Flag)&lt;/p&gt;
&lt;p&gt;　　方向标志DF用来决定在串操作指令执行时有关指针寄存器发生调整的方向。具体规定在第5.2.11节——字符串操作指令——中给出。在微机的指令系统中，还提供了专门的指令来改变标志位DF的值。&lt;/p&gt;
&lt;p&gt;　　三、32位标志寄存器增加的标志位&lt;/p&gt;
&lt;p&gt;　　1、I/O特权标志IOPL(I/O Privilege Level)&lt;/p&gt;
&lt;p&gt;　　I/O特权标志用两位二进制位来表示，也称为I/O特权级字段。该字段指定了要求执行I/O指令的特权级。如果当前的特权级别在数值上小于等于IOPL的值，那么，该I/O指令可执行，否则将发生一个保护异常。&lt;/p&gt;
&lt;p&gt;　　2、嵌套任务标志NT(Nested Task)&lt;/p&gt;
&lt;p&gt;　　嵌套任务标志NT用来控制中断返回指令IRET的执行。具体规定如下：&lt;/p&gt;
&lt;p&gt;　　(1)、当NT=0，用堆栈中保存的值恢复EFLAGS、CS和EIP，执行常规的中断返回操作；
　　(2)、当NT=1，通过任务转换实现中断返回。&lt;/p&gt;
&lt;p&gt;　　3、重启动标志RF(Restart Flag)&lt;/p&gt;
&lt;p&gt;　　重启动标志RF用来控制是否接受调试故障。规定：RF=0时，表示”接受”调试故障，否则拒绝之。在成功执行完一条指令后，处理机把RF置为0，当接受到一个非调试故障时，处理机就把它置为1。&lt;/p&gt;
&lt;p&gt;　　4、虚拟8086方式标志VM(Virtual 8086 Mode)&lt;/p&gt;
&lt;p&gt;　　如果该标志的值为1，则表示处理机处于虚拟的8086方式下的工作状态，否则，处理机处于一般保护方式下的工作状态。&lt;/p&gt;
&lt;p&gt;下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=61312&amp;amp;uk=1493685990&#34;&gt;汇编指令助手&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>WPF主题分享及使用</title>
      <link>http://blog.leaver.me/2012/09/18/wpf%E4%B8%BB%E9%A2%98%E5%88%86%E4%BA%AB%E5%8F%8A%E4%BD%BF%E7%94%A8/</link>
      <pubDate>Tue, 18 Sep 2012 09:19:02 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/18/wpf%E4%B8%BB%E9%A2%98%E5%88%86%E4%BA%AB%E5%8F%8A%E4%BD%BF%E7%94%A8/</guid>
      <description>&lt;p&gt;首先是一个很流行的WPF20多种xaml主题合集源码。这个主题系列是非常漂亮的。我找到了源码。但是没有找到官网。
update：感谢&lt;a href=&#34;http://luacloud.com/&#34;&gt;月亮云&lt;/a&gt;的提醒，官网是：http://wpfthemes.codeplex.com
截两幅图如下：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27351_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/58b8894bc549351c298072c998486b597d88cf6c.png&#34; title=&#34;theme1&#34;&gt;&lt;/a&gt;
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/27352_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b0597e4db9818945c1cf69a8be46725f1c45213f.jpg&#34; title=&#34;theme2&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;使用很简单。一种是将WPF.Theme.dll导入。像demo展示的那样。使用其提供的主题管理类来使用。可以实现任意切换效果。另一种就是直接把源文件的各种theme.xaml提取出来，添加到资源字典就行了。当然还有一些不重要的小细节。相信你对wpf比较了解的话可以搞得定的。。还可以自己学习一下。。&lt;/p&gt;
&lt;p&gt;昨天还看到一个主题，也比较漂亮。&lt;a href=&#34;http://amazingwpfcontrols.codeplex.com/&#34;&gt;Amazing WPF Controls&lt;/a&gt;分享一下。如果有什么疑问。欢迎留言讨论。&lt;/p&gt;
&lt;p&gt;下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=55959&amp;amp;uk=1493685990&#34;&gt;WPF20多种xaml主题合集源码&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>C# 委托知识总结</title>
      <link>http://blog.leaver.me/2012/09/16/c%23-%E5%A7%94%E6%89%98%E7%9F%A5%E8%AF%86%E6%80%BB%E7%BB%93/</link>
      <pubDate>Sun, 16 Sep 2012 10:52:01 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/16/c%23-%E5%A7%94%E6%89%98%E7%9F%A5%E8%AF%86%E6%80%BB%E7%BB%93/</guid>
      <description>&lt;p&gt;如果你足够强大，你就不会把幸福押在别人身上，你会自己创造幸福或者给别人带来幸福。而变得强大的途径就是学习，就是读书，学一切东西，读任何想读的书。  爱你让我变得更强。。
继续读一些专业文章了。不保证都是原创，但是保证每篇技术文章的质量。也会注明来源，标准就是浅显易懂。但不简单。&lt;/p&gt;
&lt;p&gt;原文来自：&lt;a href=&#34;http://www.cnblogs.com/qingyuan/archive/2010/05/11/1732415.html&#34;&gt;贺臣&lt;/a&gt;感谢原作者的好文章。
1.什么是委托，为什么要使用委托&lt;/p&gt;
&lt;p&gt;我正在埋头苦写程序，突然想喝水，但是又不想自己去掉杯水而打断自己的思路，于是我就想让女朋友去给我倒水。她去给我倒水，首先我得让她知道我想让她干什么，通知她之后我可以继续写自己的程序，而倒水的工作就交给了她。这样的过程就相当于一个委托。&lt;/p&gt;
&lt;p&gt;在程序过程中，当程序正在处理某个事件的时候，我需要另外的程序代码去辅助处理一些事情，于是委托另一个程序模块去处理，而委托就可以达到这种目的，我可以利用委托通知另外的程序模块，该去调用哪个函数方法。委托其实就起到了这样一个作用，将函数签名传递到了另一个函数中。或许这样讲还是有些模糊，看看后面的具体实例。&lt;/p&gt;
&lt;p&gt;2.委托的定义&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;
delegate int Add(int num1,int num2);

delegate void ConvertNum(string result);
&lt;/pre&gt;
&lt;p&gt;上面是定义两个委托的例子，其实很简单。声明一个委托使用delegate关键字，上面分别是定义的带返回值的委托和不带返回值的委托，&lt;/p&gt;
&lt;p&gt;两个委托都有传递参数，当然也可以不传递参数。其实委托也是一个类，委托派生为System.MulticastDelegate,而System.MulticastDelegate&lt;/p&gt;
&lt;p&gt;又继承System.Delegate,如果你知道这个也就明白委托其实是一个特殊的类。
委托的简单实用例子&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;
public delegate string TeaDelegate(string spText);

     public class DelegateSource
     {
         public void TestDelegate()
         {
             Operator op = new Operator();
             TeaDelegate tea = new TeaDelegate(op.GetTea);
             Console.WriteLine(&#34;去给我倒杯水&#34;);
             Console.WriteLine();
             string result=tea(&#34;去给我倒杯水&#34;);
             Thread.Sleep(5000);
             Console.WriteLine(result);
             Console.WriteLine();
         }
     }

     public class Operator
     {
         /// &lt;summary&gt;
         /// 确定是否还有水
         /// &lt;/summary&gt;
         private bool flag = true;

         public string GetTea(string spText)
         {
             if (spText == &#34;去给我倒杯水&#34;)
             {
                 if (flag)
                 {
                     return &#34;老公,茶来了&#34;;
                 }
                 else
                 {
                     return &#34;老公,没有水了&#34;;
                 }
             }
             return &#34;等待.......&#34;;
         }
     }&lt;/pre&gt;
&lt;p&gt;输出结果
&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/&#34;&gt;&lt;/p&gt;
&lt;p&gt;上面使用最普通的一种方式来定义了一个委托的使用，这个例子虽然很简单，但是能够很形象的描述委托的使用。&lt;/p&gt;
&lt;p&gt;3.委托的三种形式&lt;/p&gt;
&lt;p&gt;(1).推断
推断委托例子&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;
public delegate string TeaDelegate(string spText);

     public class DelegateSource
     {
         public void TestDelegate()
         {
             Operator op = new Operator();
             TeaDelegate tea = op.GetTea;
             Console.WriteLine(&#34;去给我倒杯水&#34;);
             Console.WriteLine();
             string result=tea(&#34;去给我倒杯水&#34;);
             Thread.Sleep(5000);
             Console.WriteLine(result);
             Console.WriteLine();
         }
     }

     public class Operator
     {
         /// &lt;summary&gt;
         /// 确定是否还有水
         /// &lt;/summary&gt;
         private bool flag = true;

         public string GetTea(string spText)
         {
             if (spText == &#34;去给我倒杯水&#34;)
             {
                 if (flag)
                 {
                     return &#34;老公,茶来了&#34;;
                 }
                 else
                 {
                     return &#34;老公,没有水了&#34;;
                 }
             }
             return &#34;等待.......&#34;;
         }
     }
&lt;/pre&gt;
&lt;p&gt;在委托定义的例子中我们看到委托的使用方法是在委托实例化的时候指定的[new DelegateName(FunctionName)],这里可能表述不是太但是代码应该看得白了。 而委托的推断，并没有new 委托这个步骤，而是直接将Function 指定给委托。&lt;/p&gt;</description>
    </item>
    <item>
      <title>WCF读书笔记(2)</title>
      <link>http://blog.leaver.me/2012/09/06/wcf%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B02/</link>
      <pubDate>Thu, 06 Sep 2012 22:09:48 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/06/wcf%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B02/</guid>
      <description>&lt;p&gt;&lt;strong&gt;信道形状（Channel Shape）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　用来表述不同的消息交换模式对消息交换双方信道（信息交换的管道）的不同要求，有什么IOutputChannel IReplyChannel IDuplexChannel之类的。。&lt;/p&gt;
&lt;p&gt;　　对于IReplyChannel，服务器返回一个RequestContext类型，作为请求和回复之间的一道桥梁，可以获取也可以返回消息。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;会话信道（Session Channel）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　从状态保持的角度，信道可以分为两种类型，Datagram Channel和Session Channel，前者不和客户端绑定，后者可以识别客户端。&lt;/p&gt;
&lt;p&gt;　　对于WCF的信道层来说，信道管理器在客户端和服务端扮演不同的角色。服务端的信道管理器用于监听来自客户端的请求，而客户端的信道仅仅是单纯创建用于请求发送和回复接收的信道，因此服务端的消息管理器又称为信道监听器（Channel Listener），客户端的信道管理器则称之为信道工厂（Channel Factory）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;绑定元素（Binding Element）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　构成一个绑定对象的元素，绑定实现了通信的所有细节，通过创建信道栈实现对消息的交换，系统绑定是指服务于某种类型场景的绑定元素的有序集合。 包括什么BaseHttpBinding之类的。&lt;/p&gt;
&lt;p&gt;　　&lt;strong&gt;一个程序集&lt;/strong&gt;包括元数据，中间语言代码，和资源。程序集已经加载，将一直保存在内存中，直到应用程序域卸载。最好摒弃添加服务引用的服务调用方式，而是直接将包含服务契约的程序集部署到客户端。客户端以直接创建代理的方式进行调用。&lt;/p&gt;
&lt;p&gt;　　WCF可以看成是适配器，是CLR类型和XML两个不同世界的纽带。&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;strong&gt;封送（Marshaling）&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;</description>
    </item>
    <item>
      <title>使用Microsoft Web Deploy技术自动部署</title>
      <link>http://blog.leaver.me/2012/09/04/%E4%BD%BF%E7%94%A8microsoft-web-deploy%E6%8A%80%E6%9C%AF%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2/</link>
      <pubDate>Tue, 04 Sep 2012 14:03:18 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/04/%E4%BD%BF%E7%94%A8microsoft-web-deploy%E6%8A%80%E6%9C%AF%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2/</guid>
      <description>&lt;p&gt;　　在前段时间使用WCF的时候。部署到服务器上一直不得要领。出现各种问题。最终搞定。原文图很多，我给个摘要，大家还是原文看。因为原文写于2010年。自动部署工具已经更新至第3版。所以有些按钮得好好找找。不过相信对大家都不是难事。&lt;/p&gt;
&lt;p&gt;　　本篇文章将提供一个循序渐进的教程，教你如何在一台Web服务期上安装和启用Web Deploy。接着我们演示如何使用Visual Studio通过Web Deploy直接（将文件）发布到服务器上，以及如何使用Visual Studio创建自动部署你的应用程序的安装包。&lt;/p&gt;
&lt;p&gt;　　&lt;strong&gt;Web Deploy—为什么你会喜欢它&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　部署一个Web应用程序或站点包含好几个步骤。您通常需要：&lt;/p&gt;
&lt;p&gt;　　1. 拷贝文件和文件夹；&lt;/p&gt;
&lt;p&gt;　　2. 提供数据库结构，或许还要生成一些数据库数据；&lt;/p&gt;
&lt;p&gt;　　3. 在文件和文件夹上设置相应的读写和安全访问控制列表；&lt;/p&gt;
&lt;p&gt;　　4. 安装和配置SSL认证；&lt;/p&gt;
&lt;p&gt;　　5. 部署其它杂七杂八的依赖项（事件日志，GAC库，COM对象等等）。&lt;/p&gt;
&lt;p&gt;　　手工执行上面的步骤又累又慢又危险（因为手工部署总是容易出错）。使用自动化流程，可以让你在一台服务器上快速维护和部署应用程序，减少出错的几率，并极大加快你在应用程序上的改动放到作业服务器上的周期。&lt;/p&gt;
&lt;p&gt;　　去原文看看吧。&lt;a href=&#34;http://blog.joycode.com/scottgu/archives/2010/11/03/116148.joy&#34;&gt;使用Microsoft Web Deploy技术自动部署&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>SQLServer启用xp_cmdshell</title>
      <link>http://blog.leaver.me/2012/07/11/sqlserver%E5%90%AF%E7%94%A8xp_cmdshell/</link>
      <pubDate>Wed, 11 Jul 2012 14:20:21 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/11/sqlserver%E5%90%AF%E7%94%A8xp_cmdshell/</guid>
      <description>&lt;p&gt;忘了当时是执行哪条命令的时候需要启动xp_cmdshell了。。反正是必须用的。。&lt;/p&gt;
&lt;p&gt;默认情况下,sql server安装完后,xp_cmdshell是禁用的(可能是安全考虑),如果要使用它,可按以下步骤&lt;/p&gt;
&lt;pre class=&#34;lang:pgsql decode:true&#34;&gt;-- 允许配置高级选项
EXEC sp_configure &#39;show advanced options&#39;, 1
GO
-- 重新配置
RECONFIGURE
GO
-- 启用xp_cmdshell
EXEC sp_configure &#39;xp_cmdshell&#39;, 1
GO
--重新配置
RECONFIGURE
GO

--执行想要的xp_cmdshell语句
Exec xp_cmdshell &#39;query user&#39;
GO

--用完后,要记得将xp_cmdshell禁用(出于安全考虑)
-- 允许配置高级选项
EXEC sp_configure &#39;show advanced options&#39;, 1
GO
-- 重新配置
RECONFIGURE
GO
-- 禁用xp_cmdshell
EXEC sp_configure &#39;xp_cmdshell&#39;, 0
GO
--重新配置
RECONFIGURE
GO&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>C# 线程优秀文章汇总</title>
      <link>http://blog.leaver.me/2012/07/11/c%23-%E7%BA%BF%E7%A8%8B%E4%BC%98%E7%A7%80%E6%96%87%E7%AB%A0%E6%B1%87%E6%80%BB/</link>
      <pubDate>Wed, 11 Jul 2012 14:04:07 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/11/c%23-%E7%BA%BF%E7%A8%8B%E4%BC%98%E7%A7%80%E6%96%87%E7%AB%A0%E6%B1%87%E6%80%BB/</guid>
      <description>&lt;p&gt;最近在看线程的东西，整理一些文档以便学习。分享。&lt;/p&gt;
&lt;h3 id=&#34;刚刚&#34;&gt;&lt;a href=&#34;http://www.cnblogs.com/xugang&#34;&gt;刚刚&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42528&#34;&gt;C#多线程学习(一) 多线程的相关概念&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42529&#34;&gt;C#多线程学习(二) 如何操纵一个线程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42530&#34;&gt;C#多线程学习(三) 生产者和消费者&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42531&#34;&gt;C#多线程学习(四) 多线程的自动管理(线程池)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42532&#34;&gt;C#多线程学习(五) 多线程的自动管理(定时器)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://kb.cnblogs.com/page/42533&#34;&gt;C#多线程学习(六) 互斥对象&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/xugang/archive/2011/03/20/1989782.html&#34;&gt;C# 实现多线程的同步方法详解&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;jimmyzheng&#34;&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng&#34;&gt;JimmyZheng&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/06/10/2543143.html&#34;&gt;C# 温故而知新： 线程篇(一)&lt;/a&gt; &lt;strong&gt;Thread&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/07/07/2580253.html&#34;&gt;C# 温故而知新： 线程篇(二)&lt;/a&gt; 线程池和异步线程&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;zhoufoxcn&#34;&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn&#34;&gt;zhoufoxcn&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn/article/details/4402999&#34;&gt;C#多线程编程（1）：线程的启动&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn/article/details/5170815&#34;&gt;多线程编程(2)：线程的同步&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn/article/details/5177579&#34;&gt;多线程编程(3)：线程池ThreadPool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn/article/details/5205690&#34;&gt;多线程编程(4)：多线程与UI操作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/zhoufoxcn/article/details/2453803&#34;&gt;一个简单的C#多线程间同步的例子&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;老赵&#34;&gt;&lt;a href=&#34;http://www.cnblogs.com/JeffreyZhao&#34;&gt;老赵&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JeffreyZhao/archive/2009/07/22/thread-pool-1-the-goal-and-the-clr-thread-pool.html&#34;&gt;浅谈线程池（上）：线程池的作用及CLR线程池&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JeffreyZhao/archive/2009/07/24/thread-pool-2-dedicate-pool-and-io-pool.html&#34;&gt;浅谈线程池（中）：独立线程池的作用及IO线程池&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JeffreyZhao/archive/2009/10/20/thread-pool-3-lab.html&#34;&gt;浅谈线程池（下）：相关试验及注意事项&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;bloodish&#34;&gt;&lt;a href=&#34;http://www.cnblogs.com/bloodish&#34;&gt;bloodish&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/bloodish/archive/2011/03/21/1990025.html&#34;&gt;C# Tip &amp;ndash; 如何优雅的控制线程状态&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;autumoon&#34;&gt;&lt;a href=&#34;http://www.cnblogs.com/Autumoon&#34;&gt;Autumoon&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/Autumoon/archive/2008/06/19/1225684.html&#34;&gt;白话多线程&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    <item>
      <title>《Effective C#》Item 9：区别和认识四个判等函数</title>
      <link>http://blog.leaver.me/2012/07/05/effective-c%23item-9%E5%8C%BA%E5%88%AB%E5%92%8C%E8%AE%A4%E8%AF%86%E5%9B%9B%E4%B8%AA%E5%88%A4%E7%AD%89%E5%87%BD%E6%95%B0/</link>
      <pubDate>Thu, 05 Jul 2012 22:56:00 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/05/effective-c%23item-9%E5%8C%BA%E5%88%AB%E5%92%8C%E8%AE%A4%E8%AF%86%E5%9B%9B%E4%B8%AA%E5%88%A4%E7%AD%89%E5%87%BD%E6%95%B0/</guid>
      <description>&lt;p&gt;　　.Net有四个判等函数？不少人看到这个标题，会对此感到怀疑。事实上确是如此，.Net提供了ReferenceEquals、静态Equals，具体类型的Equals以及==操作符这四个判等函数。但是这四个函数之间有细微的关系，改变其中一个函数的实现会影响到其他函数的操作结果。&lt;/p&gt;
&lt;p&gt;　　首先要说的是Object.ReferenceEquals和Object.Equals这两个静态函数，对于它们俩来说，是不需要进行重写的，因为它们已经完成它们所要得做的操作。&lt;/p&gt;
&lt;p&gt;对于Object.ReferenceEquals这个静态函数，函数形式如下：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;public static bool ReferenceEquals( object left, object right );&lt;/pre&gt;
&lt;p&gt;　　这个函数就是判断两个引用类型对象是否指向同一个地址。有此说明后，就确定了它的使用范围，即只能对于引用类型操作。那么对于任何值类型数据操作，即使是与自身的判别，都会返回false。这主要因为在调用此函数的时候，值类型数据要进行装箱操作，也就是对于如下的形式来说。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;int n = 10;
Object.ReferenceEquals( n, n );&lt;/pre&gt;
&lt;p&gt;这是因为对于n这个数据装箱两次，而每次装箱后的地址有不同，而造成Object.ReferenceEquals( n, n )的结果永远为false。&lt;/p&gt;
&lt;p&gt;对于第一个判等函数来说，没有什么好扩展的，因为本身已经很好地完成了它所要做的。&lt;/p&gt;
&lt;p&gt;对于第二个Object.Equals这个静态函数，其形式如下：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;public static bool Equals( object left, object right );&lt;/pre&gt;
&lt;p&gt;　　按照书中对它的分析，其大致函数代码如下：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;public static void Equals( object left, object right )
{
  // Check object identity
  if( left == right )
     return true;

// both null references handled above
if( ( left == null ) || ( right == null ) )
   return false;
  return left.Equals( right );
}&lt;/pre&gt;
&lt;p&gt;　可以说，Object.Equals这个函数完成判等操作，需要经过三个步骤，&lt;/p&gt;
&lt;p&gt;第一步是需要根据对象所属类型的==操作符的执行结果；&lt;/p&gt;
&lt;p&gt;第二步是判别是否为null，也是和第一步一样，需要根据类型的==操作符的执行结果；&lt;/p&gt;
&lt;p&gt;最后一步要使用到类型的Equals函数的执行结果。&lt;/p&gt;
&lt;p&gt;也就是说这个静态函数的返回结果，要取决于后面要提到的两个判等函数。类型是否提供相应的判等函数，成为这个函数返回结果的重要因素。&lt;/p&gt;
&lt;p&gt;　　那么对于Object.Equals这个静态方法来说，虽说接受参数的类型也属于引用类型，但是不同于Object.ReferenceEquals函数，对于如下的代码，能得出正确的结果。&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;int n = 10;
Debug.WriteLine( string.Format( &#34;{0}&#34;, Object.Equals( n, n ) ) );
Debug.WriteLine( string.Format( &#34;{0}&#34;, Object.Equals( n, 10 ) ) );&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;这是因为在此函数中要用到具体类型的两个判等函数，不过就函数本身而言，该做的判断都做了，因此不需要去重载添加复杂的操作。&lt;/p&gt;
&lt;p&gt;为了更好的述说剩下两个函数，先解释一下等价的意义。对于等价的意义，就是自反、对称以及传递。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;所谓自反，即a == a；&lt;/li&gt;
&lt;li&gt;而对称，是a == b，则b == a；&lt;/li&gt;
&lt;li&gt;传递是 a == b，b == c，则 a == c；
理解等价的意义后，那么在实现类型的判等函数也要满足这个等价规则。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;对于可以重载的两个判等函数，首先来介绍的是类型的Equals函数，其大致形式如下：&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true&#34;&gt;public override bool Equals( object right );

那么对于一个类型的Equals要做些什么操作呢，一般来说大致如下：
public class KeyData
{
private int nData;
public int Data
{
   get{ return nData;}
   set{ nData = value; }
}

public override bool Equals( object right )
{
//Check null
if( right == null )
   return false;

//check reference equality
if( object.ReferenceEquals( this, right ) )
   return true;

//check type
if( this.GetType() != right.GetType() )
   return false;

//convert to current type
  KeyData rightASKeyData = right as KeyData;

//check members value
  return this.Data == rightASKeyData.Data;
 }
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>各种内存卡介绍</title>
      <link>http://blog.leaver.me/2012/06/30/%E5%90%84%E7%A7%8D%E5%86%85%E5%AD%98%E5%8D%A1%E4%BB%8B%E7%BB%8D/</link>
      <pubDate>Sat, 30 Jun 2012 10:50:19 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/30/%E5%90%84%E7%A7%8D%E5%86%85%E5%AD%98%E5%8D%A1%E4%BB%8B%E7%BB%8D/</guid>
      <description>&lt;p&gt;闪存卡（Flash Card）是利用闪存（Flash Memory）技术达到存储电子信息的存储器，一般应用在数码相机，掌上电脑，MP3等小型数码产品中作为存储介质，所以样子小巧，有如一张卡片，所以称之为闪存卡。
根据不同的生产厂商和不同的应用，闪存卡大概有Compact Flash（CF卡）、MultiMediaCard（MMC卡）、Secure Digital（SD卡）、Memory Stick（记忆棒）等。&lt;/p&gt;
&lt;h3 id=&#34;sd卡&#34;&gt;SD卡&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;SD卡全称为Secure Digital卡，SD卡标准的面世相对而言比CF要晚，根据MMC为基础所开发的Secure Digital（SD），其改进主要是在增添了版权保护的功能，提高了传输速度和增加了写保护机制等，其主要引脚的定义与MMC卡并没有太大的区别。SD具有较高的兼容性，较小的体积和不错的数据传输速度，成为了当今的时尚数码相机和部分可拍照手机的标准配置。SD接口是当今世界上被采用得最多的闪存卡接口，市面上主流的PDA，数码相机，MP3的闪存卡，烧录卡接口大多为SD卡，也使SD卡取代了CF卡成为了当今最常见得存储卡。如图：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23896_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2153197222ee2fc8af342682b19e6a2a79c2b08b.jpg&#34; title=&#34;sd&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;minisd&#34;&gt;MiniSD&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;MiniSD是SD卡的一大改进，体积只有21.5x20x1.4mm，比普通SD卡足足节省了60%的空间，通过转接卡还能保证MiniSD在正常的SD插槽上的使用。如图：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23897_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/97f2744e4c4365467f49bb608eee282112a6b4bd.jpg&#34; title=&#34;minisd&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;micro-sdtf卡&#34;&gt;Micro SD(TF卡)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;TF卡又称T-Flash卡，也叫Micro SD卡,体积只有11×15×1mm，面积为MiniSD的一半
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23899_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2528565eb580dae155b5a2ed0de54fd37ed3729c.jpg&#34; title=&#34;tf&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;mmc卡&#34;&gt;MMC卡&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;MMC卡全称为Multi Media Card，由SanDisk与Siemens AG/InfineonTechnologies AG所联合开发，且于1997年11月发表，Size：24mm x 32mm x 1.4mm，重量2g。MMC卡的兼容性方面不及SD卡的好，数据传输速度受到硬件的限制，不适合作高速的数据传输。如图：
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23895_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ff18b0edf52209988da0c6cb442471e7eb13f081.jpg&#34; title=&#34;mmc&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;rsmmc&#34;&gt;RSMMC&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;RSMMC是Reduced-Size MMC的缩写，小型化的MMC卡，传说专门为智能手机设置。改良后的产品叫做MMCmobile
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23898_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/7ab03d9515b994a1d11aee05279f6e3d9dae53a1.jpg&#34; title=&#34;rsmmc&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;什么是cf卡&#34;&gt;什么是CF卡？&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;CF格式由来已久，被SanDisk公司在1994年首次制造出来。CF卡的全称是Compact Flash，Compact意指“小型的，轻便的”，CF大小为43mm x 36mm x 3.3mm，50 Pins。如图
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/23894_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/eddacf9fa2afe927665cf30d192070687d5c951f.jpg&#34; title=&#34;CF&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;ms卡&#34;&gt;MS卡&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Memory Stick，索尼推出的存储产品。貌似是独树一帜，不多介绍。
参考：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&#34;http://www.allmemorycards.com/sd.htm&#34;&gt;http://www.allmemorycards.com/sd.htm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://baike.baidu.com/view/26952.htm&#34;&gt;http://baike.baidu.com/view/26952.htm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://nds.cngba.com/nds_bd/2007122122100.shtml&#34;&gt;http://nds.cngba.com/nds_bd/2007122122100.shtml&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>对不起，我等不了你了</title>
      <link>http://blog.leaver.me/2012/06/27/%E5%AF%B9%E4%B8%8D%E8%B5%B7%E6%88%91%E7%AD%89%E4%B8%8D%E4%BA%86%E4%BD%A0%E4%BA%86/</link>
      <pubDate>Wed, 27 Jun 2012 10:33:09 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/27/%E5%AF%B9%E4%B8%8D%E8%B5%B7%E6%88%91%E7%AD%89%E4%B8%8D%E4%BA%86%E4%BD%A0%E4%BA%86/</guid>
      <description>&lt;p&gt;　　这不是我写的，这篇文章也不是讲爱情的，来自&lt;a href=&#34;https://xutuo.wordpress.com/2012/05/10/%E5%AF%B9%E4%B8%8D%E8%B5%B7%EF%BC%8C%E6%88%91%E7%AD%89%E4%B8%8D%E4%BA%86%E4%BD%A0%E4%BA%86/&#34;&gt;XuTuo的方式&lt;/a&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;　　学生生涯是一个很美好的时刻，当然这种美好往往得等失去了才知道珍惜。就像记忆中的高中班主任总是苦口婆心地告诉我们，拼一拼，过了这一个月，你们就解放了。年幼的人有种向往年长人的生活的冲动，这种原始的冲动就像小时候注册QQ的时候总喜欢把年龄放大到十八岁，好像花季雨季里总会有那么些纯纯的爱恋等着我们。而直到了那个季节才发现原来小说里都是骗人的，这里除了长个不停的青春痘还有做不完的作业与考不完的试，爱情是战乱里的奢侈品，珍贵且易碎。&lt;/p&gt;
&lt;p&gt;　　一群刚考完试的高考生们疯狂地撕掉课本，然后撒向天空大吼说：“我终于解放了！”接下去的几天里他们不停地聚会，不停地唱K，不停地喝酒，不停地网路短信暧昧，然后接下来是高中“革命一辈”的“生离死别”。 说着一生一世的誓言走上两条反方向的路，我喜欢那个时候忽明忽暗的爱恋，喜欢就是喜欢，不喜欢就是不喜欢，表白的那个男生可能以后会考上一所名牌大学，毕业后能当上国家公务员，家里供有着一套以及一套以上的房子让他结婚。但不喜欢就是不喜欢，因为他胖，他油性皮肤，他的校服一个礼拜都没洗，还有，他的字不好看。&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;/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;/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;/p&gt;
&lt;p&gt;　　我等不了你了，少年。&lt;/p&gt;</description>
    </item>
    <item>
      <title>c#温故而知新： 线程篇</title>
      <link>http://blog.leaver.me/2012/06/24/c%23%E6%B8%A9%E6%95%85%E8%80%8C%E7%9F%A5%E6%96%B0-%E7%BA%BF%E7%A8%8B%E7%AF%87/</link>
      <pubDate>Sun, 24 Jun 2012 10:57:38 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/24/c%23%E6%B8%A9%E6%95%85%E8%80%8C%E7%9F%A5%E6%96%B0-%E7%BA%BF%E7%A8%8B%E7%AF%87/</guid>
      <description>&lt;p&gt;上次的&lt;a href=&#34;http://leaver.me/archives/431.html&#34;&gt;C#温故而知新：Stream篇&lt;/a&gt; 已经完结了，这次，&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/&#34;&gt;JimmyZheng&lt;/a&gt; 开始更新线程了，转发收藏，持续更新，当然你也可以直接去看JimmyZheng的文章，欢迎学习交流&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/06/10/2543143.html&#34;&gt;c#温故而知新： 线程篇(一)：&lt;strong&gt;Thread&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.cnblogs.com/JimmyZheng/archive/2012/07/07/2580253.html&#34;&gt;c#温故而知新： 线程篇(二)：&lt;strong&gt;线程池和异步线程&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    <item>
      <title>GET和POST有什么区别？及为什么网上的多数答案都是错的。</title>
      <link>http://blog.leaver.me/2012/06/19/get%E5%92%8Cpost%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%E5%8F%8A%E4%B8%BA%E4%BB%80%E4%B9%88%E7%BD%91%E4%B8%8A%E7%9A%84%E5%A4%9A%E6%95%B0%E7%AD%94%E6%A1%88%E9%83%BD%E6%98%AF%E9%94%99%E7%9A%84/</link>
      <pubDate>Tue, 19 Jun 2012 18:04:40 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/19/get%E5%92%8Cpost%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%E5%8F%8A%E4%B8%BA%E4%BB%80%E4%B9%88%E7%BD%91%E4%B8%8A%E7%9A%84%E5%A4%9A%E6%95%B0%E7%AD%94%E6%A1%88%E9%83%BD%E6%98%AF%E9%94%99%E7%9A%84/</guid>
      <description>&lt;p&gt;今天突然看到很多好的技术文章，转载收藏备用分享。&lt;/p&gt;
&lt;p&gt;如果有人问你，&lt;strong&gt;GET&lt;strong&gt;&lt;strong&gt;和POST&lt;/strong&gt;&lt;/strong&gt;，有什么区别？你会如何回答？&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;我的经历&#34;&gt;我的经历&lt;/h2&gt;
&lt;p&gt;前几天有人问我这个问题。我说GET是用于获取数据的，POST，一般用于将数据发给服务器之用。&lt;/p&gt;
&lt;p&gt;这个答案好像并不是他想要的。于是他继续追问有没有别的区别？我说这就是个名字而已，如果服务器支持，他完全可以把GET改个名字叫GET2。他反问道，那就是单纯的名字上的区别喽？我想了想，我觉得如果说再具体的区别，只能去看RFC文档了，还&lt;strong&gt;要取决于服务器（指&lt;strong&gt;&lt;strong&gt;Apache&lt;/strong&gt;&lt;/strong&gt;，IIS****）的具体实现&lt;/strong&gt;。但我不得不承认，我的确没有仔细看过HTTP的RFC文档。于是我说，我对HTTP协议不太熟悉。这个问题也就结束了。&lt;/p&gt;
&lt;h2 id=&#34;最普遍的答案&#34;&gt;最普遍的答案&lt;/h2&gt;
&lt;p&gt;回来之后寻思了很久，他到底是想问我什么？我一直就觉得GET和POST没有什么除了语义之外的区别，自打我开始学习Web编程开始就是这么理解的。&lt;/p&gt;
&lt;p&gt;可能很多人都已经猜到了，他要的答案是：&lt;/p&gt;
&lt;p&gt;1. GET使用URL或Cookie传参。而POST将数据放在BODY中。&lt;/p&gt;
&lt;p&gt;2. GET的URL会有长度上的限制，则POST的数据则可以非常大。&lt;/p&gt;
&lt;p&gt;3. POST比GET安全，因为数据在地址栏上不可见。&lt;/p&gt;
&lt;p&gt;但是很不幸，**这些区别全是错误的，**更不幸的是，&lt;a href=&#34;https://www.google.com/search?q=get%E5%92%8Cpost%E7%9A%84%E5%8C%BA%E5%88%AB&amp;amp;ie=utf-8&amp;amp;oe=utf-8&amp;amp;aq=t&amp;amp;rls=org.mozilla:zh-CN:official&amp;amp;client=firefox-a&amp;amp;channel=fflb&#34;&gt;这个答案还是Google搜索的头版头条&lt;/a&gt;，然而我根本没想着这些是答案，因为在我看来他们都是错的。我来一一解释一下。&lt;/p&gt;
&lt;h3 id=&#34;get和post与数据如何传递没有关系&#34;&gt;GET和POST与数据如何传递没有关系&lt;/h3&gt;
&lt;p&gt;GET和POST是由&lt;a href=&#34;http://www.w3.org/Protocols/rfc2616/rfc2616.html&#34;&gt;HTTP协议定义&lt;/a&gt;的。在HTTP协议中，Method和Data（URL， Body， Header）是正交的两个概念，也就是说，&lt;strong&gt;使用哪个Method与应用层的数据如何传输是没有相互关系的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;HTTP没有要求，如果Method是POST数据就要放在BODY中。也没有要求，如果Method是GET，数据（参数）就一定要放在URL中而不能放在BODY中。&lt;/p&gt;
&lt;p&gt;那么，网上流传甚广的这个说法是从何而来的呢？我&lt;a href=&#34;http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.1&#34;&gt;在HTML标准中，找到了相似的描述&lt;/a&gt;。这和网上流传的说法一致。但是这只是HTML标准对HTTP协议的用法的约定。怎么能当成GET和POST的区别呢？&lt;/p&gt;
&lt;p&gt;而且，现代的Web Server都是支持GET中包含BODY这样的请求。虽然这种请求不可能从浏览器发出，但是现在的Web Server又不是只给浏览器用，已经完全地超出了HTML服务器的范畴了。&lt;/p&gt;
&lt;p&gt;知道这个有什么用？我不想解释了，有时候就得自己痛一次才记得住。&lt;/p&gt;
&lt;h3 id=&#34;http协议对get和post都没有对长度的限制&#34;&gt;HTTP协议对GET和POST都没有对长度的限制&lt;/h3&gt;
&lt;p&gt;HTTP协议明确地指出了，HTTP头和Body都没有长度的要求。而对于URL长度上的限制，有两方面的原因造成：&lt;/p&gt;
&lt;p&gt;1. 浏览器。据说早期的浏览器会对URL长度做限制。据说IE对URL长度会限制在2048个字符内（流传很广，而且无数同事都表示认同）。但我自己试了一下，我构造了90K的URL通过IE9访问live.com，是正常的。网上的东西，哪怕是Wikipedia上的，也不能信。&lt;/p&gt;
&lt;p&gt;2. 服务器。URL长了，对服务器处理也是一种负担。原本一个会话就没有多少数据，现在如果有人恶意地构造几个几M大小的URL，并不停地访问你的服务器。服务器的最大并发数显然会下降。另一种攻击方式是，把告诉服务器Content-Length是一个很大的数，然后只给服务器发一点儿数据，嘿嘿，服务器你就傻等着去吧。哪怕你有超时设置，这种故意的次次访问超时也能让服务器吃不了兜着走。有鉴于此，多数服务器出于安全啦、稳定啦方面的考虑，会给URL长度加限制。但是这个限制是针对所有HTTP请求的，与GET、POST没有关系。&lt;/p&gt;
&lt;h3 id=&#34;安全不安全和getpost没有关系&#34;&gt;安全不安全和GET、POST没有关系&lt;/h3&gt;
&lt;p&gt;我觉得这真是中国特色。我讲个小段子，大家应该可以体会出这个说法多么的可笑。&lt;/p&gt;
&lt;p&gt;觉得POST数据比GET数据安全的人会说&lt;/p&gt;
&lt;p&gt;_    “防君子不防小人；中国小白多，能防小白用户就行了。”_&lt;/p&gt;
&lt;p&gt;_    “哼，”&lt;em&gt;我不以为然，&lt;/em&gt;“那你怎么不说，_&lt;em&gt;URL__参数都Encode__过了，或是Base64__一下，小白也看不懂啊。”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;那人反驳道，_“_&lt;em&gt;Encode__太简单了，聪明点儿的小白很容易就可以Decode__并修改掉。”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;我笑道，_“五十步笑百步耳，再聪明点儿的小白还会截包并重发呢，_&lt;em&gt;Opera__就有这功能。”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;那人阴险地祭出&lt;strong&gt;神器——最终解释权&lt;/strong&gt;，说，&lt;strong&gt;&lt;em&gt;“这个不算小白。”&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我日啊。&lt;/p&gt;
&lt;h2 id=&#34;最后一点儿感想&#34;&gt;最后一点儿感想&lt;/h2&gt;
&lt;p&gt;我之前一直做Windows桌面应用，对Web开发无甚了解，直到一年多前转做服务器端开发，才开始接触到HTTP。（注意，我说的是HTTP，不是HTML。服务器开放接口是基于REST理念设计的，使用的协议是HTTP，但是传输的内容不是HTML。这不是Web Server，而是一个Web Service）&lt;/p&gt;
&lt;p&gt;所以我对于GET和POST的理解，是纯粹地来源于HTTP协议。他们只有&lt;strong&gt;一点&lt;/strong&gt;根本区别，简单点儿说，一个用于获取数据，一个用于修改数据。具体的请参考RFC文档。&lt;/p&gt;
&lt;p&gt;如果一个人一开始就做Web开发，很可能把HTML对HTTP协议的使用方式，当成HTTP协议的唯一的合理使用方式。从而犯了以偏概全的错误。&lt;/p&gt;
&lt;p&gt;可能有人会觉得我钻牛角尖。我只是不喜欢模棱两可，不喜欢边界不清、概念不明，不喜欢“拿来主义”，也不喜欢被其它喜欢钻牛角尖的人奚落得无地自容。&lt;/p&gt;
&lt;p&gt;“知之为知之，不知为不知，是知也。”&lt;/p&gt;
&lt;p&gt;原文链接：&lt;a href=&#34;http://www.cnblogs.com/nankezhishi/archive/2012/06/09/2542968.html&#34;&gt;http://www.cnblogs.com/nankezhishi/archive/2012/06/09/2542968.html&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>SASS用法指南</title>
      <link>http://blog.leaver.me/2012/06/19/sass%E7%94%A8%E6%B3%95%E6%8C%87%E5%8D%97/</link>
      <pubDate>Tue, 19 Jun 2012 17:03:49 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/19/sass%E7%94%A8%E6%B3%95%E6%8C%87%E5%8D%97/</guid>
      <description>&lt;div&gt;
&lt;p&gt;作者： &lt;a href=&#34;http://www.ruanyifeng.com/&#34;&gt;阮一峰&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;日期： &lt;a href=&#34;http://www.ruanyifeng.com/blog/2012/06/&#34;&gt;2012年6月19日&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;main-content&#34;&gt;
&lt;div&gt;
&lt;p&gt;学过&lt;a href=&#34;http://zh.wikipedia.org/wiki/%E5%B1%82%E5%8F%A0%E6%A0%B7%E5%BC%8F%E8%A1%A8&#34;&gt;CSS&lt;/a&gt;的人都知道，它不是一种编程语言。&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;more&#34;&gt;
&lt;p&gt;你可以用它开发网页样式，但是没法用它编程。也就是说，CSS基本上是设计师的工具，不是程序员的工具。在程序员眼里，CSS是一件很麻烦的东西。它没有变量，也没有条件语句，只是一行行单纯的描述，写起来相当费事。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/24063303e3abc5d5089bc58bdba65c550be0f8cb.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;很自然地，有人就开始为CSS加入编程元素，这被叫做&lt;a href=&#34;http://www.catswhocode.com/blog/8-css-preprocessors-to-speed-up-development-time&#34;&gt;&amp;ldquo;CSS预处理器&amp;rdquo;&lt;/a&gt;（css preprocessor）。它的基本思想是，用一种专门的编程语言，进行网页样式设计，然后再编译成正常的CSS文件。&lt;/p&gt;
&lt;p&gt;各种&amp;quot;CSS预处理器&amp;quot;之中，我自己最喜欢&lt;a href=&#34;http://sass-lang.com/&#34;&gt;SASS&lt;/a&gt;，觉得它有很多优点，打算以后都用它来写CSS。下面是我整理的用法总结，供自己开发时参考，相信对其他人也有用。&lt;/p&gt;
&lt;p&gt;============================================&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SASS用法指南&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;作者：阮一峰&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/c00b9e9a6c97811cb70a4f18ec85976f493eb3e7.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一、什么是SASS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://sass-lang.com/&#34;&gt;SASS&lt;/a&gt;是一种CSS的开发工具，提供了许多便利的写法，大大节省了设计者的时间，使得CSS的开发，变得简单和可维护。&lt;/p&gt;
&lt;p&gt;本文总结了SASS的主要用法。我的目标是，有了这篇文章，日常的一般使用就不需要去看&lt;a href=&#34;http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html&#34;&gt;官方文档&lt;/a&gt;了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;二、安装和使用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.1 安装&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SASS是Ruby语言写的，但是两者的语法没有关系。不懂Ruby，照样使用。只是必须先&lt;a href=&#34;http://www.ruby-lang.org/zh_cn/downloads/&#34;&gt;安装Ruby&lt;/a&gt;，然后再安装SASS。&lt;/p&gt;
&lt;p&gt;假定你已经安装好了Ruby，接着在命令行输入下面的命令：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;gem install sass
然后，就可以使用了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;2.2 使用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SASS文件就是普通的文本文件，里面可以直接使用CSS语法。文件后缀名是.scss，意思为Sassy CSS。&lt;/p&gt;
&lt;p&gt;下面的命令，可以在屏幕上显示.scss文件转化的css代码。（假设文件名为test。）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;sass test.scss
如果要将显示结果保存成文件，后面再跟一个.css文件名。
sass test.scss test.css
SASS提供四个编译风格的选项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;nested：嵌套缩进的css代码，它是默认值。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;expanded：没有缩进的、扩展的css代码。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;compact：简洁格式的css代码。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;compressed：压缩后的css代码。
生产环境当中，一般使用最后一个选项。
sass &amp;ndash;style compressed test.sass test.css
SASS的官方网站，提供了一个&lt;a href=&#34;http://sass-lang.com/try.html&#34;&gt;在线转换器&lt;/a&gt;。你可以在那里，试运行下面的各种例子。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;三、基本用法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.1 变量&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SASS允许使用变量，所有变量以$开头。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;$blue : #1875e7;&lt;/p&gt;
&lt;p&gt;div {
color : $blue;
}
如果变量需要镶嵌在字符串之中，就必须需要写在#{}之中。
$side : left;&lt;/p&gt;
&lt;p&gt;.rounded {
border-#{$side}-radius: 5px;
}
&lt;strong&gt;3.2 计算功能&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;SASS允许在代码中使用算式：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;body {
margin: (14px/2);
top: 50px + 100px;
right: $var * 10%;
}
&lt;strong&gt;3.3 嵌套&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;SASS允许选择器嵌套。比如，下面的CSS代码：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;div h1 {
color : red;
}
可以写成：
div {
hi {
color:red;
}
}
属性也可以嵌套：
p {
border-color: red;
}
可以写成：
p {
border: {
color: red;
}
}
注意，border后面必须加上冒号。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;3.4 注释&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SASS共有两种注释风格。&lt;/p&gt;
&lt;p&gt;标准的CSS注释 /* comment */ ，会保留到编译后的文件。&lt;/p&gt;
&lt;p&gt;单行注释 // comment，只保留在SASS源文件中，编译后被省略。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;四、代码的重用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4.1 继承&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;SASS允许一个选择器，继承另一个选择器。比如，现有class1：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;.class1 {
border: 1px solid #ddd;
}
class2要继承class1，就要使用@extend命令：
.class2 {
@extend .class1;
font-size:120%;
}
&lt;strong&gt;4.2 Mixin&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Turing机、人工智能以及我们的世界</title>
      <link>http://blog.leaver.me/2012/06/02/turing%E6%9C%BA%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E4%BB%A5%E5%8F%8A%E6%88%91%E4%BB%AC%E7%9A%84%E4%B8%96%E7%95%8C/</link>
      <pubDate>Sat, 02 Jun 2012 07:58:25 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/06/02/turing%E6%9C%BA%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E4%BB%A5%E5%8F%8A%E6%88%91%E4%BB%AC%E7%9A%84%E4%B8%96%E7%95%8C/</guid>
      <description>&lt;p&gt;　　matrix67大牛太帅了。&lt;a href=&#34;http://www.matrix67.com/blog/archives/4930&#34;&gt;这篇文章&lt;/a&gt;给我很大的震撼，他传递的信息远不止计算机世界。强烈推荐，精彩的部分做了引用，事实上，全都很精彩啊。&lt;/p&gt;
&lt;p&gt;　　昨天终于读完了《The Annotated Turing》一书，第一次完整地阅读了 Turing 最经典的那篇论文，理解了 Turing 机提出的动机和由此带来的一系列结论。不过，这本书的最大价值，则是让我开始重新认识和思考这个世界。在这里，我想把我以前积累的哲学观点和最近一些新的思考记下来，与大家一同分享。《The Annotated Turing》一书中的一些学术内容，留待以后几篇日志与大家分享。今年是 Alan Turing 诞辰 100 周年，图灵公司将推出这本书的中译本&lt;a href=&#34;http://www.ituring.com.cn/book/801&#34;&gt;《图灵的秘密》&lt;/a&gt;，现在正在紧张的编辑排版中，不久之后就能和大家见面。&lt;/p&gt;
&lt;p&gt;　　1928 年， David Hilbert 提出了一个著名的问题：是否存在一系列有限的步骤，它能判定任意一个给定的数学命题的真假？这个问题就叫做 Entscheidungsproblem ，德语“判定性问题”的意思。大家普遍认为，这样的一套步骤是不存在的，也就是说我们没有一种判断一个数学命题是否为真的通用方法。为了证明这一点，真正的难题是将问题形式化：什么叫做“一系列有限的步骤”？当然，现在大家知道，这里所说的“有限的步骤”指的就是由条件语句、循环语句等元素搭建而成的一个机械过程，也就是我们常说的“算法”。不过，在没有计算机的时代，人们只能模模糊糊地体会“一个机械过程”的意思。 1936 年，Alan Turing 在著名的论文《On computable numbers, with an application to the Entscheidungsproblem》中提出了一种假想的机器，第一次给了“机械过程”一个确凿的含义。&lt;/p&gt;
&lt;p&gt;　　Turing 提出的机器非常简单。假设有一张无穷向右延伸的纸条，从左至右分成一个一个的小格子。每一个小格子里都可以填写一个字符（通常是单个数字或者字母）。纸条下方有一个用来标识“当前格子”的箭头，在机器运行过程中，箭头的位置会不断移动，颜色也会不断变化。不妨假设初始时所有格子都是空白，箭头的颜色是红色，并且指向左起第一个格子。为了让机器实现不同的功能，我们需要给它制定一大堆指令。每条指令都是由五个参数构成，格式非常单一，只能形如“如果当前箭头是红色，箭头所在格子写的是字符 A ，则把这个格子里的字符改为 B ，箭头变为绿色并且向右移动一格”，其中最后箭头的移动只能是“左移一格”、“右移一格”、“不动”中的一个。&lt;/p&gt;
&lt;p&gt;　　精心设计不同的指令集合，我们就能得到功能不同的 Turing 机。你可以设计一个生成自然数序列的 Turing 机，或者是计算根号 2 的 Turing 机，甚至是打印圆周率的 Turing 机。 Turing 本人甚至在论文中实现了这么一种特殊的 Turing 机叫做通用 Turing 机，它可以模拟别的 Turing 机的运行。具体地说，如果把任意一个 Turing 机的指令集用 Turing 自己提出的一种规范方式编码并预存在纸条上，那么通用 Turing 机就能够根据纸条上已有的信息，在纸条的空白处模拟那台 Turing 机的运作，输出那台 Turing 机应该输出的东西。&lt;/p&gt;
&lt;p&gt;　　但是， Turing 机并不是无所不能的。 Turing 证明了一个看似有些惊人的事实：不存在这样的一个 Turing 机，它能读取任意一个 Turing 机的指令集，并判断该 Turing 机是否将会在纸条上打印出至少一个 0 。注意，简单地用通用 Turing 机做模拟并不是一个可行的方案，因为模拟到现在还没有打出 0 ，不意味着今后也就永远不会打出 0 。这个定理有一个更深刻的含义，即没有一种通用的方法可以预测一台 Turing 机无穷远后的将来（后人把这个结论简化为了著名的&lt;a href=&#34;http://www.matrix67.com/blog/archives/55&#34;&gt;停机问题&lt;/a&gt;）。正如《The Annotated Turing》封底上的一段文字所说：在没有计算机的时代， Turing 不但探索了计算机能做的事，还指出了计算机永远不能做到的事。&lt;/p&gt;
&lt;p&gt;　　在论文的最后一章， Turing 给出了一种 Turing 机指令集和一阶逻辑表达式的转换规则，使得这个 Turing 机将会打出 0 来，当且仅当对应的一阶逻辑表达式为真。然而，我们没有一种判断 Turing 机是否会输出 0 的算法，因此我们也就没有一种判断数学命题是否为真的通用办法。于是， Entscheidungsproblem 有了一个完美的解答。&lt;/p&gt;
&lt;p&gt;　　有趣的是，Turing 机本身的提出比 Entscheidungsproblem 的解决意义更大。计算机诞生以后，出现了五花八门的高级编程语言，一个比一个帅气，但它们的表达能力实际上都没有超过 Turing 机。事实上，再庞大的流程图，再复杂的数学关系，再怪异的语法规则，最终都可以用 Turing 机来描述。 Turing 机似乎是一个终极工具，它似乎能够表达一切形式的计算方法，可以描述一切事物背后的规律。在同一时代，美国数学家 Alonzo Church 创立了 λ 算子（λ-calculus），用数学的方法去阐释“机械过程”的含义。后来人们发现， Turing 机和 λ 算子是等价的，它们具有相同的表达能力，是描述“可计算性”的两种不同的模型。 Turing 机和 λ 算子真的能够描述所有直观意义上的“可计算数”、“可计算数列”、“可计算函数”吗？有没有什么东西超出了它们的表达能力？这个深刻的哲学问题就叫做 Church–Turing thesis 。当然，我们没法用形式化的方法对其进行论证，不过大家普遍认为， Turing 机和 λ 算子确实已经具有描述世间一切复杂关系的能力了。人们曾经提出过一些 hypercomputer ，即超出 Turing 机范围的假想机器，比如能在有限时间里运行无穷多步的机器，能真正处理实数的机器，等等。不过这在理论上都是不可能实现的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>从hash函数到王小云的MD5破解</title>
      <link>http://blog.leaver.me/2012/05/15/%E4%BB%8Ehash%E5%87%BD%E6%95%B0%E5%88%B0%E7%8E%8B%E5%B0%8F%E4%BA%91%E7%9A%84md5%E7%A0%B4%E8%A7%A3/</link>
      <pubDate>Tue, 15 May 2012 13:26:14 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/15/%E4%BB%8Ehash%E5%87%BD%E6%95%B0%E5%88%B0%E7%8E%8B%E5%B0%8F%E4%BA%91%E7%9A%84md5%E7%A0%B4%E8%A7%A3/</guid>
      <description>&lt;p&gt;　　以前一直纳闷不是说md5是不可逆的吗，那王小云怎么能破解呢。看到此文，豁然开朗，所谓的破解只是可以获得一个碰撞，使得两个文件的md5值一样。并不是说给定一个md5，能够得到原文。&lt;/p&gt;
&lt;p&gt;　　密码学是理论计算机的一个很大的方向。之前准备先写密码学概论再提在hash函数破解上做出重大贡献的王小云教授的工作，不过前两天&lt;a href=&#34;http://www.cast.org.cn/n435777/n435799/n928596/n930124/35475.html&#34;&gt;王小云获得求是杰出科学家奖以及100万奖金&lt;/a&gt;，在媒体上又掀起了一轮宣传狂潮，但是有些报道极端弱智，错误百出，所以我趁机纠正一下，并介绍密码学的一个组成部分——hash函数，以及王小云在这上面的工作。&lt;/p&gt;
&lt;p&gt;　　王小云的主要工作是关于hash函数的破解工作。她在2005一个密码学会议上宣布破解了SHA-1，震惊了全世界。所以要介绍和理解她的工作，先看一下hash函数具体是怎么回事。&lt;/p&gt;
&lt;p&gt;　　简单的说，&lt;strong&gt;hash函数&lt;/strong&gt;就是&lt;span style=&#34;color: #ff0000;&#34;&gt;把任意长的输入字符串变化成固定长的输出字符串&lt;/span&gt;的一种函数。通俗得说，hash函数用来生成信息的摘要。输出字符串的长度称为hash函数的&lt;strong&gt;位数&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;　　目前应用最为广泛的hash函数是**&lt;a href=&#34;http://en.wikipedia.org/wiki/SHA_hash_functions&#34;&gt;SHA-1&lt;/a&gt;&lt;strong&gt;和&lt;/strong&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/Md5&#34;&gt;MD5&lt;/a&gt;**，大多是128位和更长。&lt;/p&gt;
&lt;p&gt;　　hash函数在现实生活中应用十分广泛。很多下载网站都提供下载文件的MD5码校验，可以用来判别文件是否完整。另外，比如在WordPress的数据库，所有密码都是保存的MD5码，这样即使数据库的管理员也无法知道用户的原始密码，避免隐私泄露（很多人在不同地方都是用的同一个密码）。&lt;/p&gt;
&lt;p&gt;　　如果两个输入串的hash函数的值一样，则称这两个串是一个&lt;strong&gt;碰撞&lt;/strong&gt;(&lt;strong&gt;Collision&lt;/strong&gt;)。既然是把任意长度的字符串变成固定长度的字符串，所以，必有一个输出串对应无穷多个输入串，碰撞是必然存在的。&lt;/p&gt;
&lt;p&gt;　　一个“优良”的hash函数 _f _应当满足以下三个条件：　&lt;/p&gt;
&lt;p&gt;　　1.任意y，找x，使得f(x)=y，非常困难。&lt;/li&gt;
　　2.给定x1，找x2，使得f(x1)=f(x2)，非常困难。&lt;/li&gt;
　　3.找x1，x2，使得f(x1)=f(x2)，非常困难。&lt;/li&gt;&lt;/p&gt;
&lt;p&gt;　　上面的“非常困难”的意思是除了枚举外不可能有别的更快的方法。比如第3条，根据&lt;a href=&#34;http://en.wikipedia.org/wiki/Birthday_paradox&#34;&gt;生日定理&lt;/a&gt;，要想找到这样的x1，x2，理论上需要大约2^(n/2)的枚举次数。&lt;/p&gt;
&lt;p&gt;　　几乎所有的hash函数的破解，都是指的破坏上面的第三条性质，即找到一个碰撞（前两条都能被破坏的hash函数也太弱了点，早就被人抛弃了）。在密码学上还有一个概念是&lt;strong&gt;理论破解&lt;/strong&gt;，指的是提出一个算法，使得可以用低于理论值得枚举次数找到碰撞。&lt;/p&gt;
&lt;p&gt;　　王小云的主要工作是给出了MD5，&lt;a href=&#34;http://en.wikipedia.org/wiki/SHA_hash_functions&#34;&gt;SHA-0&lt;/a&gt;的碰撞，以及SHA-1的理论破解，她证明了160位SHA-1，只需要大约2^69次计算就能找出来，而理论值是2^80次。她的寻找MD5碰撞的方法是极端高效的。传说王小云当时在会议上把碰撞写出来，结果被下面的人验证发现不对，原来她把MD5算法的一个步骤弄错了。但是她立马联系她的当时留在中国的学生，修正算法，并找到一个新的碰撞。这一个是对的。&lt;/p&gt;
&lt;p&gt;　　看到这里，那些认为中国国安局应该将这些结果封存作为秘密武器甚至幻想用这些成果来袭击美国之徒可以停住你们的YY了。这种形式上的破解，在大多数情况下没有实际性的作用。更别提MD5早就被美国人抛弃了。&lt;/p&gt;
&lt;p&gt;　　但是，说这种破解一点实际意义都没有，那就侮辱了广大密码学家的智商，密码学家不会无缘无故的弄出碰撞这么一个概念来。下面简单的介绍一下在特定情况下，怎么利用给定的碰撞来做坏事(翻译自&lt;a href=&#34;http://th.informatik.uni-mannheim.de/people/lucks/HashCollisions/&#34;&gt;Attacking Hash Functions&lt;/a&gt;)：&lt;/p&gt;
&lt;p&gt;　　Caesar给实习生Alice叫写了一封推荐信(letter)。同一天，Alice叫Caesar在推荐信上数字签名，并提供了一份推荐信的电子板。Caesar打开文件，发现和原件一模一样。所以他在文件上签了名。&lt;/p&gt;
&lt;p&gt;　　几个月后，Caesar发现他的秘密文件被非法察看。这到底是怎么回事呢？&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.cits.rub.de/imperia/md/content/magnus/letter_of_rec.ps&#34;&gt;&lt;img alt=&#34;letter&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/867e9ee66a7ab1aed4342dcb1a98489a6ab17134.png&#34;&gt; &lt;/a&gt;&lt;a href=&#34;http://www.cits.rub.de/imperia/md/content/magnus/order.ps&#34;&gt;&lt;img alt=&#34;order&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/1a84f3c37a7c98c13605362aa25991c19b6d2d7b.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　&lt;img alt=&#34;(apply MD5 to both documents)&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/bf67e539f3da6867fc8a9070b940b83ff6daed5d.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;　　a25f7f0b 29ee0b39 68c86073 8533a4b9&lt;/p&gt;
&lt;p&gt;　　事实上，Alice要求Caesar签名的文件&lt;a href=&#34;http://www.cits.rub.de/imperia/md/content/magnus/letter_of_rec.ps&#34;&gt;letter&lt;/a&gt;已经被Alice做了手脚，准确地说，Alice还准备了另外一个文件&lt;a href=&#34;http://www.cits.rub.de/imperia/md/content/magnus/order.ps&#34;&gt;order&lt;/a&gt;，它们的MD5码完全一致。而Caesar的数字签名还依赖于MD5算法，所以Alice用order文件替换Letter文件之后，Caesar的数字签名依然有效。那封order给Alice提供了察看秘密文件的权限。&lt;/p&gt;
&lt;p&gt;　　具体的实现方法可见&lt;a href=&#34;http://www.cits.rub.de/imperia/md/content/magnus/rump_ec05.pdf&#34;&gt;Hash Functions and the Blind Passenger Attack&lt;/a&gt;。我在这里简单的解释一下(只是大致思路，具体实现方式，需要对文件结构信息有所了解)：&lt;/p&gt;
&lt;p&gt;　　letter文件的内容是：
　　　　if(x1==x1) show &amp;ldquo;letter&amp;rdquo; else show &amp;ldquo;order&amp;rdquo;
　　order文件的内容是：　　　
　　　　if(x2==x1) show &amp;ldquo;letter&amp;rdquo; else show &amp;ldquo;order&amp;rdquo;
　　其中字符串&amp;quot;letter&amp;quot;和&amp;quot;order&amp;quot;代表两封信实际显示的内容。x1，x2是一个MD5的碰撞。&lt;/p&gt;
&lt;p&gt;　　上面的方法，只供参考和学术用途，实际使用所引起的后果概不负责。　　
　　参考：
　　１.&lt;a href=&#34;http://th.informatik.uni-mannheim.de/people/lucks/HashCollisions/&#34;&gt;Attacking Hash Functions by Poisoned Messages &amp;ldquo;The Story of Alice and her Boss&amp;rdquo;&lt;/a&gt;
　　２.&lt;a href=&#34;http://en.wikipedia.org/wiki/Hash_function&#34;&gt;Hash function&lt;/a&gt;, wikipedia　
　　３.&lt;a href=&#34;http://en.wikipedia.org/wiki/SHA_hash_functions&#34;&gt;SHA&lt;/a&gt;, wikipedia
　　４.Interview with Yiqun Lisa Yin concerning the attack on SHA-1　&lt;/p&gt;
&lt;p&gt;　　原文来自：&lt;a href=&#34;http://zhiqiang.org/blog/science/computer-science/preliminary-computer-theory-xiao-yun-wang-from-the-hash-function-to-crack-md5.html&#34;&gt;http://zhiqiang.org&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>中文编码杂谈</title>
      <link>http://blog.leaver.me/2012/05/02/%E4%B8%AD%E6%96%87%E7%BC%96%E7%A0%81%E6%9D%82%E8%B0%88/</link>
      <pubDate>Wed, 02 May 2012 11:25:38 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/02/%E4%B8%AD%E6%96%87%E7%BC%96%E7%A0%81%E6%9D%82%E8%B0%88/</guid>
      <description>&lt;p&gt;本文来自&lt;a href=&#34;http://www.searchtb.com/2012/04/chinese_encode.html&#34;&gt;http://www.searchtb.com/2012/04/chinese_encode.html&lt;/a&gt;,讲的不错。收藏分享。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;编码问题的例子&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在Windows自带的Notepad（记事本）程序中输入“联通”两个字，保存后再次打开，会发现“联通”不见了，代之以“��ͨ”的乱码。这是Windows平台上典型的中文编码问题。即文件保存的时候是按照ANSI编码（其实就是GB2312，后面会详细介绍）保存，打开的时候程序按照UTF-8方式对内容解释，于是就出现了乱码。避免乱码的方式很简单，在“文件”菜单中选择“打开”命令，选择保存的文件，然后选择“ANSI”编码，此时就能看到久违的“联通”两个字了。&lt;/p&gt;
&lt;p&gt;在Linux平台上如果使用cat等命令查看文件中的中文内容时，可能出现乱码。这也是编码的问题。简单的说是文件时按照A编码保存，但是cat命令按照当前Locale设定的B编码去查看，在B和A不兼容的时候就出现了乱码。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么写这篇文章&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;中文编码由于历史原因牵扯到不少标准，在不了解的时候感觉一头雾水；但其实理解编码问题并不需要你深入了解各个编码标准，只要你明白了来龙去脉，了解了关键的知识点，就能分析和解决日常开发工作中碰到的大部分编码问题。有感于我看过的资料和文章要么不够全面，要么略显枯燥，所以通过这篇文章记录下笔者在日常工作中碰到的中文编码原理相关问题，目的主要是自我总结，如果能给读者提供一些帮助那就算是意外之喜了。由于严谨的编码标准对我来说是无趣的，枯燥的，难以记忆的，本文尝试用浅显易懂的生活语言解释中文编码相关的（也可能不相关的）一些问题，这也是为什么取名杂谈的原因。本文肯定存在不规范不全面的地方，我会在参考资料里给出官方文档的链接，也欢迎读者在评论中提出更好的表达方式&amp;amp;指出错误，不胜感激。&lt;/p&gt;
&lt;p&gt;对编码问题的理解我认为分为三个层次，第一个层次：概念，知道各个编码标准的应用场景，了解之间的差异，能分析和解决常见的一些编码问题。第二个层次：标准，掌握编码的细节，如编码范围，编码转换规则，知道这些就能自行开发编码转换工具。第三个层次，使用，了解中文的编码二进制存储，在程序开发过程中选择合理的编码并处理中文。为了避免让读者陷入编码标准的黑洞无法脱身（不相信？看看unicode的规范就明白我的意思了），同时由于编码查询&amp;amp;转换工具等都有现成工具可以使用，本文只涉及第一个层次，不涉及第二层次，在第三层次上会做一些尝试。在本文的最后提供了相关链接供对标准细节感兴趣的同学继续学习。最后，本文不涉及具体软件的乱码问题解决，如ssh，shell，vim，screen等，这些话题留给剑豪同学专文阐述。&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;strong&gt;英文的终极解决方案：ASCII&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;每个人都可以约定自己的一套编码，只要使用方之间了解就ok了。比如说咱俩约定0×10表示a，0×11表示b。在一开始也的确是这样的，出现了各式各样的编码。这样有两个问题：1. 各个编码的字符集不一样，有的多，有的少。2. 相同字符的编码也不一样。你这里a是0×10，他那里a可能是0×30。于是你保存的文件他就不能直接用，必须要转换编码。随着沟通范围的扩大，采用不同编码的人们互相通信就乱套了，这就是我们常说的：鸡同鸭讲。如果要避免这种混乱，那么大家就必须使用相同的编码规则，于是美国有关的标准化组织就出台了ASCII（American Standard Code for Information Interchange）编码，统一规定了英文常用符号用哪些二进制数来表示。ASCII是标准的单字节字符编码方案，用于基于文本的数据。&lt;/p&gt;
&lt;p&gt;ASCII最初是美国国家标准，供不同计算机在相互通信时用作共同遵守的西文字符编码标准，已被国际标准化组织（International Organization for Standardization, ISO）定为国际标准，称为ISO 646标准。适用于所有拉丁文字字母。ASCII 码使用指定的7位或8位二进制数组合来表示128或256种可能的字符。标准ASCII 码也叫基础ASCII码，使用7位二进制数来表示所有的大写和小写字母，数字0 到9、标点符号， 以及在美式英语中使用的特殊控制字符。而最高位为1的另128个字符（80H—FFH）被称为“扩展ASCII”，一般用来存放英文的制表符、部分音标字符等等的一些其它符号。&lt;/p&gt;
&lt;p&gt;其中：&lt;strong&gt;0&lt;/strong&gt;**～&lt;strong&gt;&lt;strong&gt;31&lt;/strong&gt;&lt;/strong&gt;及&lt;strong&gt;&lt;strong&gt;127(&lt;strong&gt;&lt;strong&gt;共&lt;/strong&gt;&lt;/strong&gt;33&lt;/strong&gt;&lt;/strong&gt;个****)****是控制字符或通信专用字符（其余为可显示字符），**32～126(共95个)是字符(32是空格），其中48～57为0到9十个阿拉伯数字，65～90为26个大写英文字母，97～122号为26个小写英文字母，其余为一些标点符号、运算符号等。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/f4718a7f6f7773857d978c65f5a676848ca450d7.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;现在所有使用英文的电脑终于可以用同一种编码来交流了。理解了ASCII编码，其他字母型的语言编码方案就触类旁通了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一波三折的中文编码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一次尝试：GB2312&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ASCII这种字符编码规则显然用来处理英文没有什么问题，它的出现极大的促进了信息在西方尤其是美国的传播和交流。但是对于中文，常用汉字就有6000以上，ASCII 单字节编码显然是不够用。为了粉碎美帝国主义通过编码限制中国人民使用电脑的无耻阴谋，中国国家标准总局发布了GB2312码即中华人民共和国国家汉字信息交换用编码，全称《信息交换用汉字编码字符集——基本集》，1981年5月1日实施，通行于大陆。GB2312字符集中除常用简体汉字字符外还包括希腊字母、日文平假名及片假名字母、俄语西里尔字母等字符，未收录繁体中文汉字和一些生僻字。 EUC-CN可以理解为GB2312的别名，和GB2312完全相同。&lt;/p&gt;
&lt;p&gt;GB2312是基于区位码设计的，在区位码的区号和位号上分别加上A0H就得到了GB2312编码。这里第一次提到了“区位码”，我就连带把下面这几个让人摸不到头脑的XX码一锅端了吧：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;区位码，国标码，交换码，内码，外码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;区位码&lt;/strong&gt;：就是把中文常用的符号，数字，汉字等分门别类进行编码。区位码把编码表分为94个区，每个区对应94个位，每个位置就放一个字符（汉字，符号，数字都属于字符）。这样每个字符的区号和位号组合起来就成为该汉字的区位码。区位码一般用10进制数来表示，如4907就表示49区7位，对应的字符是“学”。区位码中01-09区是符号、数字区，16-87区是汉字区，10-15和88-94是未定义的空白区。它将收录的汉字分成两级：第一级是常用汉字计3755个，置于16-55区，按汉语拼音字母/笔形顺序排列；第二级汉字是次常用汉字计3008个，置于56-87区，按部首/笔画顺序排列。在网上搜索“区位码查询系统”可以很方便的找到汉字和对应区位码转换的工具。为了避免广告嫌疑和死链，这里就不举例了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;国标码&lt;/strong&gt;： 区位码无法用于汉字通信，因为它可能与通信使用的控制码（00H&lt;del&gt;1FH）（即0&lt;/del&gt;31，还记得ASCII码特殊字符的范围吗？）发生冲突。于是ISO2022规定每个汉字的区号和位号必须分别加上32（即二进制数00100000，16进制20H），得到对应的国标交换码，简称&lt;strong&gt;国标码，交换码&lt;/strong&gt;，因此，“学”字的国标交换码计算为：&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;  00110001 00000111
+ 00100000 00100000
 -------------------
  01010001 00100111&lt;/pre&gt;
&lt;/div&gt;
用十六进制数表示即为5127H。
&lt;p&gt;&lt;strong&gt;交换码&lt;/strong&gt;：即国标交换码的简称，等同上面说的国标码。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;内码&lt;/strong&gt;：由于文本中通常混合使用汉字和西文字符，汉字信息如果不予以特别标识，就会与单字节的ASCII码混淆。此问题的解决方法之一是将一个汉字看成是两个扩展ASCII码，使表示GB2312汉字的两个字节的最高位都为1。即国标码加上128（即二进制数10000000,16进制80H）这种高位为1的双字节汉字编码即为GB2312汉字的机内码，简称为内码。20H+80H=A0H。这也就是常说的在区位码的区号和位号上分别加上A0H就得到了GB2312编码的由来。&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;  00110001 00000111
+ 10100000 10100000
  -------------------
  11010001 10100111&lt;/pre&gt;
&lt;/div&gt;
用十六进制数表示即为D1A7H。
&lt;p&gt;&lt;strong&gt;外码&lt;/strong&gt;：机外码的简称，就是汉字输入码，是为了通过键盘字符把汉字输入计算机而设计的一种编码。 英文输入时，相输入什么字符便按什么键，外码和内码一致。汉字输入时，可能要按几个键才能输入一个汉字。 汉字输入方案有成百上千个，但是这千差万别的外码输入进计算机后都会转换成统一的内码。&lt;/p&gt;
&lt;p&gt;最后总结一下上面的概念。中国国家标准总局把中文常用字符编码为94个区，每个区对应94个位，每个字符的区号和位号组合起来就是该字符的&lt;strong&gt;区位码&lt;/strong&gt;, 区位码用10进制数来表示，如4907就表示49区7位，对应的字符是“学”。 由于区位码的取值范围与通信使用的控制码（00H&lt;del&gt;1FH）（即0&lt;/del&gt;31）发生冲突。每个汉字的区号和位号分别加上32（即16进制20H）得到&lt;strong&gt;国标码，交换码。&lt;/strong&gt;“学”的国标码为5127H。由于文本中通常混合使用汉字和西文字符，为了让汉字信息不会与单字节的ASCII码混淆，将一个汉字看成是两个扩展ASCII码，即汉字的两个字节的最高位置为1，得到的编码为GB2312汉字的&lt;strong&gt;内码&lt;/strong&gt;。“学”的内码为D1A7H。无论你使用什么输入法，通过什么样的按键组合把“学”输入计算机，“学”在使用GB2312（以及兼容GB2312）编码的计算机里的内码都是D1A7H。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二次尝试：GBK&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GB2312的出现基本满足了汉字的计算机处理需要，但由于上面提到未收录繁体字和生僻字，从而不能处理人名、古汉语等方面出现的罕用字，这导致了1995年《汉字编码扩展规范》（GBK）的出现。GBK编码是GB2312编码的超集，向下完全兼容GB2312，兼容的含义是不仅字符兼容，而且相同字符的编码也相同，同时在字汇一级支持ISO/IEC10646—1和GB 13000—1的全部中、日、韩（CJK）汉字，共计20902字。GBK还收录了GB2312不包含的汉字部首符号、竖排标点符号等字符。CP936和GBK的有些许差别，绝大多数情况下可以把CP936当作GBK的别名。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三次尝试：GB18030&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GB18030编码向下兼容GBK和GB2312。GB18030收录了所有Unicode3.1中的字符，包括中国少数民族字符，GBK不支持的韩文字符等等，也可以说是世界大多民族的文字符号都被收录在内。GBK和GB2312都是双字节等宽编码，如果算上和ASCII兼容所支持的单字节，也可以理解为是单字节和双字节混合的变长编码。GB18030编码是变长编码，有单字节、双字节和四字节三种方式。&lt;/p&gt;
&lt;p&gt;其实，这三个标准并不需要死记硬背，只需要了解是根据应用需求不断扩展编码范围即可。从GB2312到GBK再到GB18030收录的字符越来越多即可。万幸的是一直是向下兼容的，也就是说一个汉字在这三个编码标准里的编码是一模一样的。这些编码的共性是变长编码，单字节ASCII兼容，对其他字符GB2312和GBK都使用双字节等宽编码，只有GB18030还有四字节编码的方式。这些编码最大的问题是2个。1. 由于低字节的编码范围和ASCII有重合，所以不能根据一个字节的内容判断是中文的一部分还是一个独立的英文字符。2. 如果有两个汉字编码为A1A2B1B2，存在A2B1也是一个有效汉字编码的特殊情况。这样就不能直接使用标准的字符串匹配函数来判断一个字符串里是否包含某一个汉字，而需要先判断字符边界然后才能进行字符匹配判断。&lt;/p&gt;
&lt;p&gt;最后，提一个小插曲，上面讲的都是大陆推行的汉字编码标准，使用繁体的中文社群中最常用的电脑&lt;a href=&#34;http://baike.baidu.com/view/1712.htm&#34;&gt;汉字&lt;/a&gt;&lt;a href=&#34;http://baike.baidu.com/view/51987.htm&#34;&gt;字符集&lt;/a&gt;标准叫大五码（Big5），共收录13,060个中文字，其中有二字为重覆编码(实在是不应该)。Big5虽普及于中国的台湾、香港与澳门等繁体中文通行区，但长期以来并非当地的国家标准，而只是业界标准。倚天中文系统、Windows等主要系统的字符集都是以Big5为基准，但厂商又各自增删，衍生成多种不同版本。2003年，Big5被收录到台湾官方标准的附录当中，取得了较正式的地位。这个最新版本被称为Big5-2003。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;天下归一Unicode&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;看了上面的多个中文编码是不是有点头晕了呢？如果把这个问题放到全世界n多个国家n多语种呢？各国和各地区自己的文字编码规则互相冲突的情况全球信息&lt;a href=&#34;http://www.edenw.com/tech/net/switch/&#34;&gt;交换&lt;/a&gt;带来了很大的麻烦。&lt;/p&gt;
&lt;p&gt;要真正彻底解决这个问题，上面介绍的那些通过扩展ASCII修修补补的方式已经走不通了，而必须有一个全新的编码系统，这个系统要可以将中文、日文、法文、德文……等等所有的文字统一起来考虑，为每一个文字都分配一个单独的编码。于是，Unicode诞生了。Unicode（统一码、万国码、单一码）为地球上（以后会包括火星，金星，喵星等）每种语言中的每个字符设定了统一并且唯一的二进制编码，以满足跨语言、跨平台进行文本转换、处理的要求。在Unicode里，所有的字符被一视同仁，汉字不再使用“两个扩展ASCII”，而是使用“1个Unicode”来表示，也就是说，所有的文字都按一个字符来处理，它们都有一个唯一的Unicode码。Unicode用数字0-0x10FFFF来映射这些字符，最多可以容纳1114112个字符，或者说有1114112个码位（码位就是可以分配给字符的数字）。&lt;/p&gt;
&lt;p&gt;提到Unicode不能不提UCS（通用字符集Universal Character Set）。UCS是由ISO制定的ISO 10646（或称ISO/IEC 10646）标准所定义的标准字符集。UCS-2用两个字节编码，UCS-4用4个字节编码。Unicode是由unicode.org制定的编码机制，ISO与unicode.org是两个不同的组织， 虽然最初制定了不同的标准; 但目标是一致的。所以自从Unicode 2.0开始， Unicode采用了与ISO 10646-1相同的字库和字码， ISO也承诺ISO10646将不会给超出0x10FFFF的UCS-4编码赋值， 使得两者保持一致。大家简单认为UCS等同于Unicode就可以了。&lt;/p&gt;
&lt;p&gt;在Unicode中：汉字“字”对应的数字是23383。在Unicode中，我们有很多方式将数字23383表示成程序中的数据，包括：UTF-8、UTF-16、UTF-32。UTF是“UCS Transformation Format”的缩写，可以翻译成Unicode字符集转换格式，即怎样将Unicode定义的数字转换成程序数据。例如，“汉字”对应的数字是0x6c49和0x5b57，而编码的程序数据是：&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;BYTE data_utf8[] = {0xE6, 0xB1, 0x89, 0xE5, 0xAD, 0x97}; // UTF-8编码
WORD data_utf16[] = {0x6c49, 0x5b57}; // UTF-16编码
DWORD data_utf32[] = {0x6c495b57}; // UTF-32编码&lt;/pre&gt;
&lt;/div&gt;
这里用BYTE、WORD、DWORD分别表示无符号8位整数，无符号16位整数和无符号32位整数。UTF-8、UTF-16、UTF-32分别以BYTE、WORD、DWORD作为编码单位。“汉字”的UTF-8编码需要6个字节。“汉字”的UTF-16编码需要两个WORD，大小是4个字节。“汉字”的UTF-32编码需要两个DWORD，大小是8个字节。根据字节序的不同，UTF-16可以被实现为UTF-16LE或UTF-16BE，UTF-32可以被实现为UTF-32LE或UTF-32BE。
&lt;p&gt;下面介绍UTF-8、UTF-16、UTF-32、BOM。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;UTF-8&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下：&lt;/p&gt;
&lt;table border=&#34;1&#34;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Unicode编码(16进制)&lt;/td&gt;
&lt;td&gt;UTF-8 字节流(二进制)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;000000 – 00007F&lt;/td&gt;
&lt;td&gt;0xxxxxxx&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;000080 – 0007FF&lt;/td&gt;
&lt;td&gt;110xxxxx 10xxxxxx&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;000800 – 00FFFF&lt;/td&gt;
&lt;td&gt;1110xxxx 10xxxxxx 10xxxxxx&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;010000 – 10FFFF&lt;/td&gt;
&lt;td&gt;11110xxx 10xxxxxx 10xxxxxx 10xxxxxx&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0×00-0x7F之间的字符，UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出，4字节模板有21个x，即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。总结了一下规律：UTF-8的第一个字节开始的1的个数代表了总的编码字节数，后续字节都是以10开始。由上面的规则可以清晰的看出UTF-8编码克服了中文编码的两个问题。
&lt;p&gt;例1：“汉”字的Unicode编码是0x6C49。0x6C49在0×0800-0xFFFF之间，使用3字节模板了：1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是：0110 1100 0100 1001， 用这个比特流依次代替模板中的x，得到：11100110 10110001 10001001，即E6 B1 89。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
