<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_懒猪乐园</title><subtitle type="text">追求卓越; 知行合一</subtitle><id>http://feed.cnblogs.com/blog/u/19552/rss</id><updated>2011-06-26T00:55:09Z</updated><author><name>Anders06</name><uri>http://www.cnblogs.com/anders06/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/anders06/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/19552/rss"/><entry><id>http://www.cnblogs.com/anders06/archive/2011/03/04/1971078.html</id><title type="text">我也谈面试 附赠一份题目</title><summary type="text">老赵一出手，又引来无数跟帖。详见 我在面试.NET/C#程序员时会提出的问题小弟不才，只被面试过，从未面试过别人。所以想从被面试方的角度来谈谈，在我心中理想的面试应该是咋个样的。前阵子lzprgmr同学，站在面试官的立场上谈了谈他的感受，见 谈谈技术面试。里面写道：首先，我觉得技术面试是需要讲究技巧的，不是随随便便拉一个技术不错的人就可以，因为面试的过程是双方相互交流的过程，你需要给对方营造一个轻松的气氛，并在不断的提问与回答的过程中，进行“合理的引导”，“适时的追问”与“正确的判断”我非常赞成他的观点，面试官跟被面试的人无论如何都很难做到绝对的平等， 面试官对题目准备充分，享有话语权，而且接</summary><published>2011-03-04T09:25:00Z</published><updated>2011-03-04T09:25:00Z</updated><author><name>Anders06</name><uri>http://www.cnblogs.com/anders06/</uri></author><link rel="alternate" href="http://www.cnblogs.com/anders06/archive/2011/03/04/1971078.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/anders06/archive/2011/03/04/1971078.html"/><content type="html">&lt;p&gt;老赵一出手，又引来无数跟帖。详见 &lt;a href="http://blog.zhaojie.me/2011/03/my-interview-questions-for-dotnet-programmers.html"&gt;我在面试.NET/C#程序员时会提出的问题&lt;/a&gt;&lt;/p&gt;&lt;p&gt;小弟不才，只被面试过，从未面试过别人。所以想从被面试方的角度来谈谈，在我心中理想的面试应该是咋个样的。&lt;/p&gt;&lt;p&gt;前阵子&lt;a href="http://home.cnblogs.com/u/baiyanhuang/"&gt;lzprgmr&lt;/a&gt;同学，站在面试官的立场上谈了谈他的感受，见 &lt;a href="http://www.cnblogs.com/baiyanhuang/archive/2011/01/23/1942605.html"&gt;谈谈技术面试&lt;/a&gt;。里面写道：&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;em&gt;首先，我觉得技术面试是需要讲究技巧的，不是随随便便拉一个技术不错的人就可以，因为面试的过程是双方相互交流的过程，你需要给对方营造一个轻松的气氛，并在不断的提问与回答的过程中，进行&amp;#8220;&lt;strong&gt;合理的引导&amp;#8221;&lt;/strong&gt;，&amp;#8220;&lt;strong&gt;适时的追问&amp;#8221;&lt;/strong&gt;与&amp;#8220;&lt;strong&gt;正确的判断&lt;/strong&gt;&amp;#8221;&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;我非常赞成他的观点，面试官跟被面试的人无论如何都很难做到绝对的平等， 面试官对题目准备充分，享有话语权，而且接受面试的人很容易也很普遍表现紧张，如果再遇到不太Nice的面试官，很容易搞坏心情，影响发挥。&lt;/p&gt;&lt;p&gt;面试的时候我比较乐意回答些开放式的问题，或者由浅入深的问题套问题的问题。有时候我们可能一上来没完全理解面试官的意图，缺失上下文，一时半会儿答不上来， 如果这样就被一票否决的话，我觉得是有失公允的。如果面试官能够稍加提示，&amp;#8220;&lt;strong&gt;合理的引导&amp;#8221;&lt;/strong&gt;，说不定就能答上来，说不定还有自己独特的见解。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p id=""&gt;面试官应该更多地考察对方想法，思路，而不是简单的考察那些 知道/不知道 很容易只有正反答案的问题。&lt;/p&gt;&lt;p&gt;比如：写一个Swap函数，不借助第三方变量。 这个问题太考验技巧了，如果之前看过，自然不难，如果没有接触过想半天也很难答的上来。况且会跟不会都说明不了什么问题，我不清楚这样的问题意义何在。 再说这道题在实际项目中一点意义也没有，我写逻辑简单，性能还不错的代码，也不愿意写羞涩难懂，标榜性能最大化的代码。 有时候这么点性能的提升真的有必要吗？&lt;/p&gt;&lt;p&gt;以上我只是就事论事谈谈对这个问题的看法，如果作为面试题，我觉得无所谓，面试嘛什么都可以谈，不管是纯技术的，还是涉及到实际项目应用的，都可谈。但千万别一棒子打死人，答不上来就觉得对方能力不行。我到更喜欢，一开始答不上，适当给点提示后，对方很快就跟上节奏的人。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;我享受如下的面试过程，LinkedList有用过吗？能简单说说跟List有什么区别吗？两者适用的场景是什么？他们各自的优势是什么，性能有什么不同，什么原因造成了性能的区别。。。&lt;/p&gt;&lt;p&gt;先抛出个简单的问题，然后&amp;#8221;&lt;strong&gt;适时的追问&amp;#8221;&lt;/strong&gt;去挖掘更深层次的问题，最好能问及到对方恰巧未思考过，不熟悉的领域，加适当地提示。我觉得这个过程式相当考验人的，而且良莠应该很容易分辨。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;我觉得：程序员的价值，不仅在于他懂得多少个知识点，更多的时候体现在于能不能融会贯通各个知识点，能不能做到举一反三。更重要的是在遇到困难，遇到新情况时所表现出来的特质，是如何思考问题的，能否从过去的经验中得到启发，并进行合理的变通，恰当地解决当下的问题。&lt;/p&gt;&lt;p&gt;最后引用我们CEO的一段话：&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;em&gt;Innovation is rarely about the creation of something entirely new; in fact, it's about looking at things from a new perspective, and changing or combining them in ways that create new value.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;老赵很大方，在博客上提前罗列了很多可能会考察的知识点，不怕应聘者做突击准备，&amp;#8220;蒙混过关&amp;#8221;：&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;em&gt;我并不担心大家知道这些问题，而且我可以表示以后的面试估计也逃不开这些。如果您有某些意向，做些针对性的准备可能也是不错的。当然，既然是面试，就会有&amp;#8220;随机应变&amp;#8221;，你我都一样。我有自信可以在不断追问下发现到底是&amp;#8220;真材实料&amp;#8221;还是&amp;#8220;临时抱佛脚&amp;#8221;。&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p id=""&gt;&amp;nbsp;我特相信，一个优秀合格的面试官确实能够大致分辨出对方的水准。反过来，合格的程序员也应该能通过一次愉快的面试，大致了解到面试官的水准，自己是不是合适加入他们的Team。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;@DeepNight同学在下面评论到: 其实仔细看了CLR via C#大多数的问题还是能答上来的。&lt;/p&gt;&lt;p&gt;我想如果你带着问题去看的话，确实都能找到答案。那对于上面未罗列的问题呢？问题背后的问题呢？你在看CLR via C#能够对所有的知识点，展开一番思考吗，多问几个问题吗？&lt;/p&gt;&lt;p&gt;《幸福课》里提到：很多事情一直都在那里，只是你没有问为什么，所以忽视了他们的存在。Question create realistic。 这句话TTM令我震撼了！&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;小弟不才，简单罗列了下几个问题，希望能够引起一番思考如果你还不会的吧&lt;img wlemoticon-smile"="" alt="Smile" src="http://images.cnblogs.com/cnblogs_com/anders06/201103/201103041725298595.png" style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none; " /&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;.NET Quiz&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;li&gt;下面两个函数签名有什么区别，能举例子详细说明下吗&amp;nbsp;&amp;nbsp; private void Modify(string str){...}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private void Modify(ref string str){...}&lt;/li&gt;&lt;li&gt;ref 和out 参数有什么区别，为什么要这样设计&lt;/li&gt;&lt;li&gt;Int? 是什么， 什么是nullable类型， 值类型 or 引用类型？ 怎么理解 int? I = null；为什么要引入Nullable类型&lt;/li&gt;&lt;li&gt;GetType() 方法有什么用， 哪里定义的， 子类可重写吗？ Int? i = 2； i.GetType() 返回的是什么类型，为什么，意义在哪里，怎么做到的？&amp;nbsp;&amp;nbsp;Int? i = null； i.GetType() 为什么会异常，真的是i没有分配空间，没有初始化引起的吗？&lt;/li&gt;&lt;li&gt;泛型和delegate 有什么共通性， 共同的理念是什么&lt;/li&gt;&lt;li&gt;什么是代码可读性， 怎么看待 可读性 VS 性能 问题&lt;/li&gt;&lt;li&gt;怎么理解封装， 就是为了屏蔽数据？ 能不能从更高的层面理解这个问题&lt;/li&gt;&lt;li&gt;Array 和 List 有什么区别； List 和 LinkedList 有什么区别； 性能，应用场合？什么是deque（double ended queue）? 不知道的话没关系，面试官给出定义，特性，要求被面试者用现有的集合类实现一个deque吧&lt;/li&gt;&lt;li&gt;try { } finally {} finally 里的代码一定能保证执行吗 ？ 如果不能，什么情况下。 throw； throw ex； 有什么区别， 什么时候需要重新抛出自定义的异常&lt;/li&gt;&lt;li&gt;Assert 是什么，平时用的多吗，什么是防御式编程？ 方法检测时，传入的参数为空情况下，是用Assert 呢还是直接抛异常?&amp;nbsp;&lt;/li&gt;&lt;li&gt;什么是面向过程编程，什么是面向对象编程，面向对象编程一定比&lt;div style="display: inline-block; "&gt;&lt;/div&gt;面向过程编程有意义吗？ 什么是面向组件开发， 什么是AOP，什么是面向服务编程， 他们有共性吗，他们的引入是为了解决什么样的问题？ 为什么历史是朝这个方向发展的， 可以倒着来吗?&amp;nbsp;&lt;/li&gt;&lt;li&gt;在主线程中进行计算密集型操作，这个时候UI能响应用户反应吗，如果要更新UI 怎么办？ 如果要用一个进度条实时反馈当前计算进度，应该怎么做？ 可以在其他线程进行如下操作吗? textBox.Text = "Name"; 为什么？ 为什么有这个限制？&amp;nbsp;&amp;nbsp;textBox.BeginInvoke( action) 做了什么事.&amp;nbsp;&amp;nbsp; &lt;/li&gt;&lt;li&gt;有人说：软件开发中所有的问题，都可以引用中间层解决。 你怎么理解？举些例子吧。&amp;nbsp;&amp;nbsp;&lt;/li&gt;&lt;li&gt;IL 是什么，引入的理念是什么？ 什么时候IL才会被编译成native代码 。 下面两段代码有什么区别 &amp;nbsp;&lt;/li&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New'; font-size: 13px; "&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New'; font-size: 13px; "&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp;代码&amp;nbsp;1：&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000FF;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Main(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[]&amp;nbsp;args)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Start&amp;nbsp;In&amp;nbsp;main&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;A&amp;nbsp;a&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;A();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;End&amp;nbsp;In&amp;nbsp;main&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp;代码&amp;nbsp;2：&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Main(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[]&amp;nbsp;args)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Start&amp;nbsp;In&amp;nbsp;main&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SimpleWrap();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;End&amp;nbsp;In&amp;nbsp;main&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SimpleWrap()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;A&amp;nbsp;a&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;A();&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;如果class A是定义在另一个工程里，运行的时候凑巧A所在的dll不在应用程序目录下，会发生什么，两者输出有不同吗?&lt;/p&gt;&lt;li&gt;ICloneable是什么，什么是浅克隆，什么深克隆，如何实现深克隆，原理是什么，你怎么理解。 如果下面函数是一事件响应函数链上一环，应该注意什么: &amp;nbsp;(提示： const &amp;nbsp;应该明白我想问什么了吧)&amp;nbsp;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff; "&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;OnPreSelected（ObjectPath&amp;nbsp;path)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;Setp&amp;nbsp;1:&amp;nbsp;check&amp;nbsp;valid&amp;nbsp;path&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;path.PopTo(...)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(path&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;...)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;附加题：一个计算密集型操作，我不想使用多线程，又希望同步进度条， 可以做到吗？ 如何做到？(提示： 消息泵， .NET 3.5）（如果有人能顺畅答上这道题，我觉得可以加50分：））&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Sunday, June 26, 2011:&lt;/p&gt;&lt;p&gt;下面2段代码有什么区别：&lt;/p&gt;&lt;p id=""&gt;&lt;font class="Apple-style-span" face="'Courier New'" size="2"&gt;&lt;span class="Apple-style-span" style="line-height: 19px;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;font class="Apple-style-span" face="'Courier New'" size="2"&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;FireMouseMove()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(mMouseMove&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mMouseMove(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;10&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;FireMouseMove()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;tempCopy&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;mMouseMove;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(tempCopy&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tempCopy&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;10&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;}&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Level 2: 什么是线程栈？&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/anders06/aggbug/1971078.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/anders06/archive/2011/03/04/1971078.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/anders06/archive/2010/11/22/1883778.html</id><title type="text">败给了IEqualityComparer</title><summary type="text">LINQ中的Distinct方法能够帮助我们轻松地剔除集合里面相同的元素。 它提供了2个重载函数，其中一个允许我们传入IEqualityComparer&lt;T&gt; 接口， 给我们充分的自由来决...</summary><published>2010-11-22T01:36:00Z</published><updated>2010-11-22T01:36:00Z</updated><author><name>Anders06</name><uri>http://www.cnblogs.com/anders06/</uri></author><link rel="alternate" href="http://www.cnblogs.com/anders06/archive/2010/11/22/1883778.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/anders06/archive/2010/11/22/1883778.html"/><content type="html">&lt;p&gt;LINQ中的Distinct方法能够帮助我们轻松地剔除集合里面相同的元素。 它提供了2个重载函数，其中一个允许我们传入IEqualityComparer&amp;lt;T&amp;gt; 接口， 给我们充分的自由来决定2个元素是否相同。&lt;/p&gt; &lt;p&gt;为了实现剔除一堆string集合中相同的string，我写下了如下的代码。 &lt;font color="#000000"&gt;&lt;strong&gt;注：不区分大小写&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;source.Distinct(new StringComparer());&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;internal class StringComparer : IEqualityComparer&amp;lt;string&amp;gt;&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool Equals(string x, string y)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return string.Compare(x, y, true) == 0;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int GetHashCode(string obj)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return obj.GetHashCode();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;}&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;结果调试的时候始终不对，结果始终不能剔除那些只是大小写有区别的字符串，如"good” 跟"Good”.&lt;/p&gt; &lt;p&gt;当时因为时间紧张，就先提交了，事后发现原来还是自己不严谨，败给了GetHashCode()方法。&lt;/p&gt; &lt;p&gt;印象中自己没怎么实现过IEqualityComparer， 到实现过多次的IComparer接口。在上面的例子中虽然我意识到在比较的时候忽略大小写，但是再实现GetHashCode(), 随手地用了上面的方式。 &lt;/p&gt; &lt;p&gt;问题就在这，既然我们认为"good” 跟"Good”是一样的，那么我们必须给他俩返回一样的hash code，但显然以我上面实现方式它俩返回的hash code是不一样的。&lt;/p&gt; &lt;p&gt;在鄙人的《&lt;a href="http://www.cnblogs.com/anders06/archive/2009/10/19/1586093.html"&gt;避免陷阱，重现Equals方法您需要注意的其中2个原则&lt;/a&gt;》与《&lt;a href="http://www.cnblogs.com/anders06/archive/2008/12/15/1355488.html"&gt;Just Reflect&lt;/a&gt; 》 中，其实我是多次提到了这个问题，想不到这次还是马失前蹄了，罪过啊。&lt;/p&gt; &lt;p&gt;所以正确的写法应该是:&lt;/p&gt; &lt;p&gt;public int GetHashCode(string obj)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return obj.ToUpper().GetHashCode();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p&gt;&lt;br&gt;扩充话题: 既然第一次写法返回的结果不正确，这就能说明Distinct扩展方法是先调用GetHashCode(), 再调用Equals(). 因为如果是先调用Equals()方面，理论上"good” 跟"Good” 是能剔除一个的。 问题是为什么要先调用GetHashCode()， 或则换种说法是为什么Distinct方法接受IEqualityComparer接口， 而不是IComparer接口。 因为判定2个对象是否相同，只需调用Equals() 方法就好。或者说因为 ICompare接口返回的是int，而不是直接的bool类型吗？那为啥不是IEquatable呢?&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;调试Framework的源代码，可以发现如下踪迹：&lt;/p&gt; &lt;p&gt;static IEnumerable&amp;lt;TSource&amp;gt; DistinctIterator&amp;lt;TSource&amp;gt;(IEnumerable&amp;lt;TSource&amp;gt; source, IEqualityComparer&amp;lt;TSource&amp;gt; comparer) {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Set&amp;lt;TSource&amp;gt; set = new Set&amp;lt;TSource&amp;gt;(comparer);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (TSource element in source)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (set.Add(element)) yield return element; &lt;br&gt;}&lt;/p&gt; &lt;p&gt;也就是说Distinct执行时在遍历集合的时候，是把那些非重复的元素放在了Set容器里，而非普通的List，这样的好处是因为Set是一个HashTable结构的容器类，可以提高执行效率。我们知道在HashTable里找一个元素的间复杂度为O(1). 而在List里查找的效率却是O(n)。&lt;/p&gt; &lt;p&gt;因此将Distinct方法接受IEqualityComparer接口，是很有必要的， 目前按照它的实现方式时间复杂度为O(n)。 而如果改为传IEquatable接口，那么时间复杂度就得变为O(n2).&lt;/p&gt;&lt;img src="http://www.cnblogs.com/anders06/aggbug/1883778.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/anders06/archive/2010/11/22/1883778.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/anders06/archive/2010/11/20/1882636.html</id><title type="text">标注随测量物体旋转问题</title><summary type="text">假设我们对如下Block中的红色线段做了标注，那么这个标注的两个锚点(Anchor Point)分别为红色线段的2个端点 当我们旋转这个Block后，我们自然希望这个标注也跟着物体旋转的，调整到如下...</summary><published>2010-11-20T08:27:00Z</published><updated>2010-11-20T08:27:00Z</updated><author><name>Anders06</name><uri>http://www.cnblogs.com/anders06/</uri></author><link rel="alternate" href="http://www.cnblogs.com/anders06/archive/2010/11/20/1882636.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/anders06/archive/2010/11/20/1882636.html"/><content type="html">&lt;p&gt;假设我们对如下Block中的红色线段做了标注，那么这个标注的两个锚点(Anchor Point)分别为红色线段的2个端点&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_2.png"&gt;&lt;img style="border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_thumb.png" width="240" height="137"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;当我们旋转这个Block后，我们自然希望这个标注也跟着物体旋转的，调整到如下合理的位置，&amp;nbsp;&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_thumb_1.png" width="240" height="226"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;现在的问题是如何为这个标注求得变换矩阵。&lt;/p&gt; &lt;p&gt;一开始我以为只要根据红色初始位置，跟终止位置，求得它的变换矩阵，再作用到标注上就可以了。 但是结果下来，发现自己想简单了。在上面第二张图中，用户可以继续绕着红色线段，旋转Block，比如得到下面的形状：&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_6.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_thumb_2.png" width="239" height="240"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;我们发现实际上第二张图跟第三张图中红色线段对应的向量是一样的,那么计算出来的变换矩阵肯定跟第二张图一样，得到的一定是下面这个错误的结果：&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_8.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_thumb_3.png" width="240" height="226"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;正确的结果应该如下：&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_10.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_thumb_4.png" width="240" height="219"&gt;&lt;/a&gt;&lt;/p&gt;   &lt;p&gt;这个问题的本质原因在于： &lt;strong&gt;一条直线不能决定平面。&lt;/strong&gt; 那么2点不能决定平面，三点总归可以了吧。关键问题就是第三个点怎么选取。这个第三个点必须相对红色线段是稳定的，那么当Block旋转后，我们依然能够找回来。于是想到了求这个Block的中心点，而后构建一个平面，根据这个平面前后位置，求得变化矩阵，问题就得以解决了。&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_12.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_thumb_5.png" width="240" height="137"&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_14.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/0162b66cd061_105E9/image_thumb_6.png" width="240" height="208"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;原始矩阵：&lt;/p&gt; &lt;p&gt;Vector3d vecX =&amp;nbsp; (p2 - p1).Normal();&lt;br&gt;Vector3d refVec = (centerPoint - p1).Mormal();&lt;br&gt;Vector3d vecZ = vecX.CrossProduct(refVec);&lt;br&gt;Vector3d vecY = vecX.CrossProduct(vecZ);&lt;br&gt;Matrix3d m0 = new Matrix3d();&lt;br&gt;m0.SetCoordinateSystem(p1, vecX, vecY, vecZ); // orignal transform&lt;/p&gt; &lt;p&gt;新的矩阵：&lt;/p&gt; &lt;p&gt;Vector3d vecX' = (p2' - p1').Normal();&lt;br&gt;Vector3d refVec' = (centerPoint' - p1').Mormal();&lt;br&gt;Vector3d vecZ' = vecX'.CrossProduct(refVec');&lt;br&gt;Vector3d vecY' = vecX'.CrossProduct(vecZ');&lt;br&gt;Matrix3d m1 = new Matrix3d();&lt;br&gt;m1.SetCoordinateSystem(p1', vecX', vecY', vecZ'); // new transform&lt;br&gt;&lt;/p&gt;  &lt;p&gt;变换矩阵：&lt;/p&gt; &lt;p&gt;Matrix3d transform = m1 * (m0.Invert());&lt;/p&gt;&lt;img src="http://www.cnblogs.com/anders06/aggbug/1882636.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/anders06/archive/2010/11/20/1882636.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/anders06/archive/2010/11/20/1882606.html</id><title type="text">How to detect memory leak issue</title><summary type="text">首先,托管代码由GC自动回收，不代表托管应用程序就没有内存泄露问题 其次, 程序不总是精确知道哪些托管对象是垃圾，这就代表着没有一款工具，一运行就能给你一个报表，说某某对象没回收，某某地方发生了内存泄...</summary><published>2010-11-20T07:27:00Z</published><updated>2010-11-20T07:27:00Z</updated><author><name>Anders06</name><uri>http://www.cnblogs.com/anders06/</uri></author><link rel="alternate" href="http://www.cnblogs.com/anders06/archive/2010/11/20/1882606.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/anders06/archive/2010/11/20/1882606.html"/><content type="html">&lt;p&gt;首先,托管代码由GC自动回收，不代表托管应用程序就没有内存泄露问题&lt;/p&gt; &lt;p&gt;其次, 程序不总是精确知道哪些托管对象是垃圾，这就代表着没有一款工具，一运行就能给你一个报表，说某某对象没回收，某某地方发生了内存泄露。&lt;/p&gt; &lt;p&gt;再次, 工具只能dump出当前应用程序的内存快照，有没有内存泄露还需要你敏锐的眼光。比如说下面的例子，当某个文档被关闭后，这个文档对象及其它引用的资源依然包含在Dump的内存快照中，我们就可推断出此处有内存泄露。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;u&gt;&lt;/u&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;u&gt;&lt;font size="4"&gt;Tool:&lt;/font&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;I used the .Net Memory Profiler tool to investigate this issue. You can get a fully functional 14 day trial version form &lt;a href="http://memprofiler.com/download.aspx"&gt;here&lt;/a&gt;, and there are some training stuff list &lt;a href="http://memprofiler.com/"&gt;here&lt;/a&gt;. &lt;p&gt;&lt;b&gt;&lt;u&gt;&lt;font size="4"&gt;Suggestion:&lt;/font&gt;&lt;/u&gt;&lt;/b&gt; &lt;p&gt;· &lt;b&gt;If any plug-in listen system events which will adds into EventManager (Application level object), please make sure remove the handlers before closing document&lt;/b&gt;. &lt;p&gt;· &lt;b&gt;Avoid implement empty destructors in C#,&amp;nbsp; try to implement &lt;i&gt;IDisposable&lt;/i&gt;&lt;/b&gt; &lt;b&gt;interface to dispose unmanaged and managed resource in Dispose method,&amp;nbsp; or&amp;nbsp; use dispose pattern.&lt;/b&gt; if any incorrect place, please correct me. &lt;p&gt;(In book of “CLR VIA C#” chapter 20, page 477, Jeffrey Richter mentioned: “&lt;i&gt;the CLR doesn't make any guarantees as to the order in which Finalize methods are called, so you should avoid writing a Finalize method that accesses other objects whose type defines a Finalize method; those other objects could have been finalized already. &lt;/i&gt;) &lt;p&gt;&amp;nbsp; &lt;p&gt;Now, please refer to the following explanation why we need to notice those. &lt;p&gt;&lt;strong&gt;&lt;u&gt;&lt;font size="4"&gt;Diagnosis:&lt;/font&gt;&lt;/u&gt;&lt;/strong&gt; &lt;ul&gt; &lt;li&gt;To make it more clear, I add two commands in &lt;i&gt;Windows&lt;/i&gt; class&amp;nbsp; , this will force GC to collect garbage:&lt;/li&gt;&lt;/ul&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/clip_image003_2.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image003" border="0" alt="clip_image003" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/clip_image003_thumb.jpg" width="240" height="47"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;ul&gt; &lt;li&gt;Next, run the application, create a default document , then close the document. Run the .Net Memory Profiler tool, and attach it to the application process, then execute “&lt;strong&gt;Collect heap Snapshot&lt;/strong&gt;” command. Now, Profiler will analyze the memory of the application. This process is very slow, in the end, we can see&amp;nbsp; the following snapshot:&lt;/li&gt;&lt;/ul&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/1_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/1_thumb.png" width="733" height="465"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;ul&gt; &lt;li&gt;Filter the Namespace to select the namespace - “xxx.xxx.xxx.xxx.Documents.Objects”, we can see there is still a copied IllustrationDocument object. However, we expect it should be 0. This tells us the IllustrationDocument object don’t&amp;nbsp; be disposed successfully.&lt;/li&gt;&lt;/ul&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/2_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="2" border="0" alt="2" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/2_thumb.png" width="820" height="345"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;ul&gt; &lt;li&gt;Double click the IllustrationDocument row, we can get this instance’s details information that also includes its reference &lt;/li&gt;&lt;/ul&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/3_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="3" border="0" alt="3" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/3_thumb.png" width="865" height="434"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;ul&gt; &lt;li&gt;Now we found there are 19 references. But some references have no problems like Asset, because the asset object’s lifecycle is in the scope of document’s lifecycle. Check the “&lt;strong&gt;Only show instance included in root paths&lt;/strong&gt;” checkbox, it will filter the references, and only show the instances included in root paths. Those references are the really killers who caused to the IllustrationDocument object couldn’t be disposed successfully:&lt;/li&gt;&lt;/ul&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/4_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="4" border="0" alt="4" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/4_thumb.png" width="873" height="172"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;(The row which mark up by red rectangle is caused by the &lt;i&gt;Renderer&lt;/i&gt; class, which forgot to remove system&amp;nbsp; events handler in its dispose method)&lt;/p&gt;&lt;/blockquote&gt; &lt;ul&gt; &lt;li&gt;Double click the highlight row in the above figure, we can look over which objects have references to &lt;i&gt;ShotEditor&lt;/i&gt; instance:&lt;/li&gt;&lt;/ul&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/5_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="5" border="0" alt="5" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/5_thumb.png" width="685" height="110"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;ul&gt; &lt;li&gt;Go on (double click the highlight row in above figure), then refer to the following:&lt;/li&gt;&lt;/ul&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/7_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="7" border="0" alt="7" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/7_thumb.png" width="694" height="108"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;ul&gt; &lt;li&gt;Go on…, finally we get the following figure:&lt;/li&gt;&lt;/ul&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/6_4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="6" border="0" alt="6" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/6_thumb_1.png" width="693" height="112"&gt;&lt;/a&gt;&lt;br&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;&lt;b&gt;&lt;i&gt;Reason: The CameraEvents has been added into EventManger class whose lifecycle is global. Any class who listens camera’s events, will cause it still keep to live, so the CLR could not mark them as garbage. This is the real reason for that we could not dispose document object successfully.&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;b&gt;&lt;u&gt;&lt;font size="4"&gt;Solution:&lt;/font&gt;&lt;/u&gt;&lt;/b&gt; &lt;p&gt;Let’s have a look at &lt;i&gt;CtxMenuForm&lt;/i&gt; source code, we will find it listens the &lt;i&gt;OnCameraEventChange&lt;/i&gt; event in its construction, but forget to remove this event handler. &lt;p&gt;So let’s do some changes for it, implement the &lt;i&gt;IDisposable&lt;/i&gt; interface: &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/8_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="8" border="0" alt="8" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/8_thumb.png" width="797" height="140"&gt;&lt;/a&gt; &lt;p&gt;Then call&amp;nbsp; form’s dispose method in someplace before close the document : &lt;p&gt;&lt;i&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/clip_image002_2.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/clip_image002_thumb.jpg" width="623" height="269"&gt;&lt;/a&gt;&lt;/i&gt; &lt;p&gt;&lt;i&gt;&lt;/i&gt; &lt;p&gt;Collect the Application memory snapshot again following above steps,&amp;nbsp; we will found the root references count reduce from 4 to 3, has no referenced by &lt;i&gt;ShotEditor&lt;/i&gt;. &lt;p&gt;The some problems also exist in &lt;i&gt;Renderer&lt;/i&gt; class and some UI class, after I do some changes for those class, remove all listened events handlers before close document, I finally remove all the root references to IllustrationDocument object, but there is still a copied IllustrationDocument object. I don’t know what’s wrong, then I refer it to MSDN, and got the following infomation: &lt;p&gt;&lt;i&gt;Implementing Finalize methods or destructors can have a negative impact on performance and you should avoid using them unnecessarily. Reclaiming the memory used by objects with Finalize methods &lt;b&gt;requires at least two garbage collections&lt;/b&gt;.&lt;/i&gt; &lt;p&gt;You can get more information from &lt;a href="http://msdn.microsoft.com/en-us/library/0s71x931.aspx"&gt;here&lt;/a&gt;. &lt;p&gt;So, I modify the &lt;i&gt;Windows&lt;/i&gt; class, try to call GC.Collect method more than twice, run the Application application, close the default document, collect its memory snapshot, the result is there is still a copied IllustrationDocument object. I am confused! Then I turn to write a small test application, it works as MSDN said. So what’s wrong? &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/clip_image027_2.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image027" border="0" alt="clip_image027" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/clip_image027_thumb.jpg" width="401" height="181"&gt;&lt;/a&gt; &lt;p&gt;After some struggle, I build a release version, then I found the document can complete dispose successfully. Refer to the following figure: &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/9_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="9" border="0" alt="9" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/8780b54ee29e_CBC5/9_thumb.png" width="973" height="348"&gt;&lt;/a&gt; &lt;p&gt; &lt;p&gt;Hope it helps.&lt;/p&gt;&lt;img src="http://www.cnblogs.com/anders06/aggbug/1882606.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/anders06/archive/2010/11/20/1882606.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/anders06/archive/2010/11/18/1881240.html</id><title type="text">图纸中角度标注算法</title><summary type="text">两条非平行线段， 如何合理的标注角度。比方说对于下面2条初始线段： 根据当前鼠标所在位置的不同，我们可能得到如下不同的标注方式： 本人求标注的思路大体思路是：首先求出圆弧（Dimension Line）的两个端点, 然后根据这两个已求得的端点，分别计算出两条引线（Witness Line）的端点。 求圆弧端点的算法： 我们把问题简化下，对于任意2条相交的射线，以下均以锐角为例(钝角求解过程完全一...</summary><published>2010-11-18T13:58:00Z</published><updated>2010-11-18T13:58:00Z</updated><author><name>Anders06</name><uri>http://www.cnblogs.com/anders06/</uri></author><link rel="alternate" href="http://www.cnblogs.com/anders06/archive/2010/11/18/1881240.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/anders06/archive/2010/11/18/1881240.html"/><content type="html">&lt;p&gt;两条非平行线段， 如何合理的标注角度。比方说对于下面2条初始线段： &lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/1.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/1_thumb.png" width="240" height="171" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;根据当前鼠标所在位置的不同，我们可能得到如下不同的标注方式： &lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/3.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="3" border="0" alt="3" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/3_thumb.png" width="240" height="220" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="4" border="0" alt="4" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/4_thumb.png" width="240" height="171" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/5.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="5" border="0" alt="5" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/5_thumb.png" width="240" height="150" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/6.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="6" border="0" alt="6" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/6_thumb.png" width="205" height="240" /&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/7.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="7" border="0" alt="7" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/7_thumb.png" width="216" height="240" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;&amp;nbsp; &lt;/p&gt;&lt;p&gt;本人求标注的思路大体思路是：首先求出圆弧（Dimension Line）的两个端点, 然后根据这两个已求得的端点，分别计算出两条引线（Witness Line）的端点。 &lt;/p&gt;&lt;h3 id=""&gt;&lt;font style="font-weight: bold"&gt;&lt;u&gt;求圆弧端点的算法：&lt;/u&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;我们把问题简化下，对于任意2条相交的射线，以下均以锐角为例(钝角求解过程完全一致)： &lt;/p&gt;&lt;p&gt;以2线段所在直线交点作为圆心， 鼠标位置到圆心的距离为半径，画一个圆，2条直线与圆必有4个交点，而Dimension Line的2个端点必然为这4个交点中的两个。&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/image_thumb.png" width="224" height="240" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;问题是我们如何从这4个交点中，选取其中的2个点作为Dimension Line的端点。 &lt;/p&gt;&lt;p&gt;方法如下：我们把上面图中的红色实心向量和蓝色实心向量，作为2个参考向量，将图切分为如下4个象限： &lt;/p&gt;&lt;p&gt;&amp;nbsp; &lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/image_4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/image_thumb_1.png" width="179" height="240" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;然后根据当前的鼠标位置，决定出应该取那个象限， 做法是 记 &lt;font style="background-color: #ffff00"&gt;value = (红色向量 X 橙色向量) . (橙色向量 X 蓝色向量)&lt;/font&gt; &lt;/p&gt;&lt;p&gt;如果得到的value值大于0，则当前鼠标必定落在一三象限，否则则在二四象限 &lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/image_6.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/image_thumb_2.png" width="165" height="240" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;接下来就是如何精确点位到鼠标是在一象限呢，还是在三象限。本人想到了用角度去推测，相信应该有更高效便捷的算法存在，只是目前自己没想到。 &lt;/p&gt;&lt;p&gt;观察上图我们可以发现：假设当前鼠标在第三象限，那么&lt;font style="background-color: #ffff00"&gt;橙色向量分别到两参考向量（红色实心向量和蓝色实心向量）的角度之和必然大于 180&amp;#176;&lt;/font&gt;，如果求得角度和小于180&amp;#176;就可断定为第一象限。(此方法钝角也依然适用，考虑下当前鼠标在上图二象限，以红色虚线向量以及蓝色实线向量作为参考向量) &lt;/p&gt;&lt;p&gt;&amp;nbsp; &lt;/p&gt;&lt;p id=""&gt;算法实现如下，思路大体跟上面一致，仅做了点优化：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('e7a11474-b736-40f7-a48e-e8cb508f76e6')"&gt;&lt;img src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" class="code_img_closed" id="code_img_closed_e7a11474-b736-40f7-a48e-e8cb508f76e6"  alt="" /&gt;&lt;img src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" class="code_img_opened" id="code_img_opened_e7a11474-b736-40f7-a48e-e8cb508f76e6" onclick="cnblogs_code_hide('e7a11474-b736-40f7-a48e-e8cb508f76e6',event)" style="display:none"&gt;&lt;div id="cnblogs_code_open_e7a11474-b736-40f7-a48e-e8cb508f76e6" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;GetDimensionLineEndPoints(LineSeg3d&amp;nbsp;firstSeg3d,&amp;nbsp;LineSeg3d&amp;nbsp;secondSeg3d,&amp;nbsp;Point3d&amp;nbsp;thirdPt,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;out&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Point3d&amp;nbsp;firstCrossPt,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;out&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Point3d&amp;nbsp;secondCrossPt)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Point3d&amp;nbsp;centerPoint&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;GetIntersectPoint(firstSeg3d,&amp;nbsp;secondSeg3d);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;double&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;radius&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;thirdPt.DistanceTo(centerPoint);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Vector3d&amp;nbsp;firstLineVec&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(firstSeg3d.EndPoint&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;centerPoint).Normal();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Vector3d&amp;nbsp;secondLineVec&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(secondSeg3d.EndPoint&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;centerPoint).Normal();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Vector3d&amp;nbsp;thirdLineVec&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(thirdPt&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;centerPoint).Normal();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;((firstLineVec.CrossProduct(thirdLineVec)).DotProduct(thirdLineVec.CrossProduct(secondLineVec))&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;secondLineVec&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt;secondLineVec;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;((thirdLineVec.AngleTo(firstLineVec)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;thirdLineVec.AngleTo(secondLineVec))&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Math.PI)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;firstLineVec&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt;firstLineVec;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;secondLineVec&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt;secondLineVec;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;firstCrossPt&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;centerPoint&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;firstLineVec&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;radius;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;secondCrossPt&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;centerPoint&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;secondLineVec&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;radius;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font style="font-weight: bold"&gt;&lt;u&gt;求引线端点的算法：&lt;/u&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/image_10.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/anders06/Windows-Live-Writer/ca8a1ace3aa8_12CBC/image_thumb_4.png" width="240" height="214" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Witness Line的2个端点为上述4个点中的两个，组合方式取决于绿色圈圈相对于其他3个点的位置，目前本人想到的方案不是很理想，看看明天能不能想到更方便简单的算法来描述，敬请等待明天的更新。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;如果大家有更好的标注算法，请不吝指教！&lt;/p&gt;&lt;img src="http://www.cnblogs.com/anders06/aggbug/1881240.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/anders06/archive/2010/11/18/1881240.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/anders06/archive/2010/08/20/1804835.html</id><title type="text">认真的程序员最可爱</title><summary type="text">记录一段小经历，当我们嗅觉到一段有问题的代码时，仔细研究下会有不错的发现。经验总结：当我们跟IntPtr打交道时一定要小心谨慎，谨防GDI泄漏Yesterday, I noticed that someimage resources in Annotation project are not defined as static, the clientdirectly access by &amp;#822...</summary><published>2010-08-20T10:07:00Z</published><updated>2010-08-20T10:07:00Z</updated><author><name>Anders06</name><uri>http://www.cnblogs.com/anders06/</uri></author><link rel="alternate" href="http://www.cnblogs.com/anders06/archive/2010/08/20/1804835.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/anders06/archive/2010/08/20/1804835.html"/><content type="html">&lt;p class="MsoNormal" id=""&gt;记录一段小经历，当我们嗅觉到一段有问题的代码时，仔细研究下会有不错的发现。&amp;nbsp;&lt;/p&gt;&lt;p id="aeaoofnhgocdbnbeljkmbjdmhbcokfdb-mousedown"&gt;经验总结：当我们跟IntPtr打交道时一定要小心谨慎，谨防GDI泄漏&lt;/p&gt;&lt;p id=""&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Yesterday, I noticed that someimage resources in Annotation project are not defined as static, the clientdirectly access by &amp;#8220;&lt;span style="font-size:9.5pt;font-family:Consolas"&gt;Properties.&lt;/span&gt;&lt;span style="color:#2B91AF"&gt;Resources&lt;/span&gt;&amp;#8230;&amp;#8221;. &lt;/p&gt;&lt;p class="MsoNormal"&gt;As far as I know is, in original we have a &amp;#8216;rule&amp;#8217; that theimage resource should defined as static in order to defense GDI leak. (I&amp;#8217;m notsure about this, because I could not find out the related mail now.)&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal" id=""&gt;So, I test the annotation ribbon, and found there does existGDI leak problem. If we change the callout shape type or toggle &amp;#8220;Keep On Top&amp;#8221;check box continuously, the GDI increased shapely, when it reach to 9999,the Application crashed. Please refer to &lt;font class="Apple-style-span" color="#003366" id=""&gt;【...】&lt;/font&gt;&lt;span class="apple-style-span"&gt;&lt;strong&gt;&lt;span style="font-size:9.0pt;font-family:&amp;quot;Arial&amp;quot;,&amp;quot;sans-serif&amp;quot;;color:#333333"&gt;.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" id=""&gt;Jerry has helped me located the key problem, that inAnimatedBusyCursor.cs class, line 66, it create a Cursor by IntPtr, but neverdestroy it.&amp;nbsp;Thanks, Jerry, it&amp;#8217;s a amazing found.&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal" id=""&gt;I have downloaded his code and tested, it works well. Allthe increased GDI object can be decrease now. So I&amp;#8217;m not sure if we still needdefined the image resource as static. In&amp;nbsp;&lt;span class="Apple-style-span" style="color: #003366; "&gt;【...】&lt;/span&gt;, I does defined the image resource as static. Please help me toreview it. If you don&amp;#8217;t mind, I want to check in those code. Any problem,please let me know.&lt;/p&gt;&lt;p class="MsoNormal" id=""&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal" id=""&gt;&lt;em id=""&gt;(It is strange to me that why it is ok now we directlyuse the image resource. I guess it may related to the some Contextual Ribbonchanges. In early time, the contextual ribbon for annotation can have severalcopies at the same time, it will created a copy when show annotation&amp;#8217;scontextual ribbon, and never released. &amp;nbsp;So if we don&amp;#8217;t defined the imageas static, it may reference more than once by the ribbon control, so the GDIincreased. Since, currently this problem has been solved, there is only onecopy contextual ribbon, so maybe directly access the image is ok. I&amp;#8217;m not sure,just guessing&lt;/em&gt;&lt;em&gt;&lt;span style="font-family:Wingdings" id=""&gt;J&lt;/span&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/em&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/anders06/aggbug/1804835.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/anders06/archive/2010/08/20/1804835.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/anders06/archive/2010/08/11/1797555.html</id><title type="text">Clean Code反案例：什么是不好的API</title><summary type="text">一个不良API例子的浅析，及重构后的结果</summary><published>2010-08-11T10:47:00Z</published><updated>2010-08-11T10:47:00Z</updated><author><name>Anders06</name><uri>http://www.cnblogs.com/anders06/</uri></author><link rel="alternate" href="http://www.cnblogs.com/anders06/archive/2010/08/11/1797555.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/anders06/archive/2010/08/11/1797555.html"/><content type="html">&lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 10px; line-height: 13pt; border-right-style: none; background-color: #ffffff; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-left: 10px; padding-right: 10px; font-family: Helvetica, Arial, sans-serif; border-top-style: none; height: 100%; color: #000000; font-size: 10pt; border-left-style: none; padding-top: 10px; background-origin: initial; background-clip: initial; " id=""&gt;&lt;p&gt;先来看两段代码：&lt;/p&gt;&lt;p&gt;&lt;span class="Apple-style-span" style="line-height: normal; color: #003366; font-weight: bold; "&gt;&lt;strong&gt;CI.cs:&lt;/strong&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="font-weight: normal; "&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;BoundBlock3d&amp;nbsp;meshOrthoBoundBlock(Matrix3d&amp;nbsp;localToBound)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Matrix3d&amp;nbsp;xfrm&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;localToBound&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;*&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.ChildToParentTransform;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.Child.meshOrthoBoundBlock(xfrm);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;h6 style="padding-bottom: 0px; line-height: normal; margin-top: 22px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-left: 0px; padding-right: 0px; color: #003366; font-size: 10pt; font-weight: bold; padding-top: 0px; "&gt;CD.cs&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('ae6ea47d-e00f-4365-a1c3-f201f5dacb73')" style="font-weight: normal; "&gt;&lt;img style="display: none" id="code_img_closed_ae6ea47d-e00f-4365-a1c3-f201f5dacb73" class="code_img_closed" alt="" src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" /&gt;&lt;img id="code_img_opened_ae6ea47d-e00f-4365-a1c3-f201f5dacb73" class="code_img_opened" onclick="cnblogs_code_hide('ae6ea47d-e00f-4365-a1c3-f201f5dacb73',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt; &lt;div id="cnblogs_code_open_ae6ea47d-e00f-4365-a1c3-f201f5dacb73"&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;BoundBlock3d&amp;nbsp;meshOrthoBoundBlock(Matrix3d&amp;nbsp;localToBound)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BoundBlock3d&amp;nbsp;rv&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;BoundBlock3d();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Matrix3d&amp;nbsp;mtx&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;localToBound&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;*&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.ScalingTransform;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;(ComponentInstance&amp;nbsp;ci&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;in&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.ReferencedComponentInstances)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rv.orthoExtend(ci.meshOrthoBoundBlock(mtx));&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rv.orthoExtend(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.Body.GetOrthoBoundingBlock(mtx));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;rv;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;类之间的简单关系： CD中包含了CI的几何信息&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/anders06/CIstructure.JPG" width="415" height="252" /&gt;&lt;/p&gt;&lt;p&gt;大家可以先看看，仔细想想，如果你一眼看出了问题，那么很是佩服你，你相当的厉害！&lt;/p&gt;&lt;p&gt;&amp;nbsp;-------------------------------------------------&amp;nbsp; 华丽的分割线&amp;nbsp; -------------------------------------------------&amp;nbsp; &lt;/p&gt;&lt;p&gt;上面这段代码问题有二：&lt;/p&gt;&lt;h6 style="padding-bottom: 0px; line-height: normal; margin-top: 22px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-left: 0px; padding-right: 0px; color: #003366; font-size: 10pt; font-weight: bold; padding-top: 0px; "&gt;一： 两个方法的修饰符 都是&lt;span style="color: #ff0000"&gt;public&lt;/span&gt;。&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个叫引诱他人犯罪， 因为当外面Client调用CI::meshOrthoBoundBlock(), 你得的结果是错误的，而且很多情况下你还不一定能注意到, 因为它多乘了CI自身的ChildToParentTransform。 你注意到了吗？如果没有理解我说的话，你只需要再研究研究CD里的逻辑。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;改进的方法是:&lt;/strong&gt;&amp;nbsp;将CI里的public修饰符改成internal， 这样就能防止外面调用CI:meshOrthoBoundBlock(), 他们才会意识到应该调用CD里的方法。&lt;/p&gt;&lt;h6 style="padding-bottom: 0px; line-height: normal; margin-top: 22px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-left: 0px; padding-right: 0px; color: #003366; font-size: 10pt; font-weight: bold; padding-top: 0px; "&gt;二：Client调用CD::meshOrthoBoundBlock()，得传什么参数好呢？&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;搜索下可以发现Client都是这么调用的 cd.meshOrthoBoundBlock(Matrix3d.Identity). Oh, shit! 大哥，我怎么知道要传入一个标准矩阵进去啊，即使大家都知道了这个潜规则，这样的接口设计就是脱裤子放屁，多此一举。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;改进的方法是：&lt;/strong&gt;封装一个不带参数的方法供外部调用，并把原先的方法访问修饰符改为internal。&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;问题一二的引入，我们发现实际上都是为了实现CD中递归计算。 第一个问题看似小问题，却是很需要讲究的，我们必须时刻注意到&lt;span style="color: #ff0000"&gt;&lt;strong&gt;封装&lt;/strong&gt;&lt;/span&gt;，尽可以封装一切。 对于修饰符的选择，必须使用最严格的，&lt;span style="color: #ff0000"&gt;千&lt;/span&gt;&lt;span style="color: #ff0000"&gt;万不要滥用public&lt;/span&gt;。&lt;/p&gt;&lt;p&gt;&lt;span style="line-height: normal; color: #003366; font-weight: bold" class="Apple-style-span"&gt;下面是我重构后代码，欢迎指正：&lt;/span&gt;&lt;/p&gt;&lt;h6 style="padding-bottom: 0px; line-height: normal; margin-top: 22px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; padding-left: 0px; padding-right: 0px; color: #003366; font-size: 10pt; font-weight: bold; padding-top: 0px; "&gt;&lt;strong&gt;CI.cs:&lt;/strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('99070bb1-80eb-4fe0-bc06-cae0248fb243')" style="font-weight: normal; "&gt;&lt;img style="display: none" id="code_img_opened_99070bb1-80eb-4fe0-bc06-cae0248fb243" class="code_img_opened" onclick="cnblogs_code_hide('99070bb1-80eb-4fe0-bc06-cae0248fb243',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&lt;span class="cnblogs_code_collapse" id=""&gt;重构后的CI&lt;/span&gt; &lt;div id="cnblogs_code_open_99070bb1-80eb-4fe0-bc06-cae0248fb243" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;BoundBlock3d&amp;nbsp;MeshOrthoBoundBlock()&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;MeshOrthoBoundBlock(Matrix3d.Identity);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;BoundBlock3d&amp;nbsp;MeshOrthoBoundBlock(Matrix3d&amp;nbsp;localToBound)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;{&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BoundBlock3d&amp;nbsp;bounds&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;BoundBlock3d();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Matrix3d&amp;nbsp;mtx&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;localToBound&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;*&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.Child.ScalingTransform;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;(CI&amp;nbsp;childCI&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;in&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.Child.ReferencedCIs)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bounds.orthoExtend(MeshOrthoBoundBlock(mtx&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;*&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;childCI.ChildToParentTransform));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;&amp;nbsp;Calculate&amp;nbsp;self&amp;nbsp;bounds&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bounds.orthoExtend(activeBody.GetOrthoBoundingBlock(mtx));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;bounds;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p id=""&gt;&lt;br /&gt;&lt;/p&gt;&lt;p id="aeaoofnhgocdbnbeljkmbjdmhbcokfdb-mousedown"&gt;&lt;span style="color: #003366"&gt;&lt;strong id=""&gt;CD.cs:&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #003366"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;移去meshOrthoBoundBlock方法&amp;nbsp;&lt;/p&gt;&lt;p&gt;大家可以看到为了避免Client传不必要的Matrix3d.Identity， 我在外面多包装了一层。现在对于外面来说会清净很多，没有混乱的API， Client应该不用头大了。&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/anders06/aggbug/1797555.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/anders06/archive/2010/08/11/1797555.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/anders06/archive/2009/10/19/1586093.html</id><title type="text">避免陷阱，重写Equals方法您需要注意的其中2个原则</title><summary type="text">相信大部分熟读过《CLR Via C#》一书的人应该明白文字代码问题出在哪里，因为道理都在那本书里摆着。至于我为什么写此文重谈一遍，一个是因为读书归读书，碰到实际情况时就不见得也能保持冷静明白个所以然，能够避免踩此陷阱； 二则我也很难理解我们的架构师为什么会犯此错误，是故意的呢还是不够仔细踩了地雷。于是写此文记录一下，以免今后自己犯此错误。各位有则改之，无则加勉</summary><published>2009-10-19T09:01:00Z</published><updated>2009-10-19T09:01:00Z</updated><author><name>Anders06</name><uri>http://www.cnblogs.com/anders06/</uri></author><link rel="alternate" href="http://www.cnblogs.com/anders06/archive/2009/10/19/1586093.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/anders06/archive/2009/10/19/1586093.html"/><content type="text">相信大部分熟读过《CLR Via C#》一书的人应该明白文字代码问题出在哪里，因为道理都在那本书里摆着。至于我为什么写此文重谈一遍，一个是因为读书归读书，碰到实际情况时就不见得也能保持冷静明白个所以然，能够避免踩此陷阱； 二则我也很难理解我们的架构师为什么会犯此错误，是故意的呢还是不够仔细踩了地雷。于是写此文记录一下，以免今后自己犯此错误。各位有则改之，无则加勉</content></entry><entry><id>http://www.cnblogs.com/anders06/archive/2009/10/14/1583357.html</id><title type="text">What’s the problems with the following code</title><summary type="text">以下代码源自于真实项目，本人只是做了一点简化，大家来找碴，看看哪些地方不妥:-)</summary><published>2009-10-14T08:43:00Z</published><updated>2009-10-14T08:43:00Z</updated><author><name>Anders06</name><uri>http://www.cnblogs.com/anders06/</uri></author><link rel="alternate" href="http://www.cnblogs.com/anders06/archive/2009/10/14/1583357.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/anders06/archive/2009/10/14/1583357.html"/><content type="text">以下代码源自于真实项目，本人只是做了一点简化，大家来找碴，看看哪些地方不妥:-)</content></entry><entry><id>http://www.cnblogs.com/anders06/archive/2009/10/09/1579726.html</id><title type="text">对象池</title><summary type="text">[代码]</summary><published>2009-10-09T08:19:00Z</published><updated>2009-10-09T08:19:00Z</updated><author><name>Anders06</name><uri>http://www.cnblogs.com/anders06/</uri></author><link rel="alternate" href="http://www.cnblogs.com/anders06/archive/2009/10/09/1579726.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/anders06/archive/2009/10/09/1579726.html"/><content type="text">[代码]</content></entry></feed>
