<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>C# on Wenrong Nexus</title>
        <link>https://wenrong-nexus.com/tags/c%23/</link>
        <description>Recent content in C# on Wenrong Nexus</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-Hant</language>
        <lastBuildDate>Sun, 31 May 2026 00:33:46 +0800</lastBuildDate><atom:link href="https://wenrong-nexus.com/tags/c%23/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>Effective C# 做法 22-23</title>
            <link>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-22-23/</link>
            <pubDate>Sun, 13 Oct 2024 03:11:00 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-22-23/</guid>
            <description>&lt;h2 id=&#34;做法-22&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-22&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 22&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;支援泛型的共變數與反變數&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-這個-out-也是-共變數&#34;&gt;&lt;a href=&#34;#1-%e9%80%99%e5%80%8b-out-%e4%b9%9f%e6%98%af-%e5%85%b1%e8%ae%8a%e6%95%b8&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 這個 out 也是 共變數?&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; TryParse (&lt;span style=&#34;color:#66d9ef&#34;&gt;string?&lt;/span&gt; s, IFormatProvider? provider, &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; result);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;方法參數中的 out 關鍵字：&#xA;在 TryParse 方法中的 out int result 是一個輸出參數。這個 out 關鍵字的作用是：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;表示這個參數是一個輸出參數。&lt;/li&gt;&#xA;&lt;li&gt;方法必須在返回前為這個參數賦值。&lt;/li&gt;&#xA;&lt;li&gt;呼叫方法時，不需要初始化這個參數，但必須在呼叫後使用它。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;在泛型接口或委託定義中使用的 out 關鍵字表示協變。例如：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; T&amp;gt; { ... }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;這裡的 out 表示：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;T 只能用作輸出（返回值），不能用作輸入（參數）。&lt;/li&gt;&#xA;&lt;li&gt;允許將更具體（派生）類型的集合賦值給更一般（基類）類型的集合變量。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;區別總結：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;用途不同：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;方法參數的 out：用於指定輸出參數。&lt;/li&gt;&#xA;&lt;li&gt;泛型的 out：用於指定類型參數的協變性。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;位置不同：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;方法參數的 out：用在方法參數列表中。&lt;/li&gt;&#xA;&lt;li&gt;泛型的 out：用在泛型類型參數定義中。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;功能不同：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;方法參數的 out：確保方法將值賦給參數。&lt;/li&gt;&#xA;&lt;li&gt;泛型的 out：允許更靈活的類型轉換和賦值。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;編譯時行為： - 方法參數的 out：編譯器確保方法內部對參數賦值。 - 泛型的 out：編譯器允許特定的類型轉換。&#xA;所以， TryParse 方法中的 out 不是用於協變的，而是一個輸出參數標記。這兩種 out 雖然使用相同的關鍵字，但在 C# 中代表完全不同的概念。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;簡單解釋共變數與反變數&#34;&gt;&lt;a href=&#34;#%e7%b0%a1%e5%96%ae%e8%a7%a3%e9%87%8b%e5%85%b1%e8%ae%8a%e6%95%b8%e8%88%87%e5%8f%8d%e8%ae%8a%e6%95%b8&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;簡單解釋共變數與反變數&#xA;&lt;/h3&gt;&lt;h4 id=&#34;共變數covariance&#34;&gt;&lt;a href=&#34;#%e5%85%b1%e8%ae%8a%e6%95%b8covariance&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;共變數（Covariance）&#xA;&lt;/h4&gt;&lt;p&gt;定義：允許使用比原本指定的類別更具體（更繼承）的類型。&#xA;關鍵字：out&#xA;應用：通常用於返回類別或只讀泛型介面。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IEnumerable&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;&amp;gt; strings = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IEnumerable&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt;&amp;gt; objects = strings; &lt;span style=&#34;color:#75715e&#34;&gt;// 合法，因為 IEnumerable&amp;lt;T&amp;gt; 是共變數&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;反變數contravariance&#34;&gt;&lt;a href=&#34;#%e5%8f%8d%e8%ae%8a%e6%95%b8contravariance&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;反變數（Contravariance）&#xA;&lt;/h4&gt;&lt;p&gt;定義：允許使用比原本指定的類別更一般（更基礎）的類別。&#xA;關鍵字：in&#xA;應用：通常用於參數類別或只寫泛型介面。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Action&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt;&amp;gt; objectAction = (&lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt; obj) =&amp;gt; Console.WriteLine(obj);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Action&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;&amp;gt; stringAction = objectAction; &lt;span style=&#34;color:#75715e&#34;&gt;// 合法，因為 Action&amp;lt;T&amp;gt; 是反變數&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;詳細解釋和更多例子&#34;&gt;&lt;a href=&#34;#%e8%a9%b3%e7%b4%b0%e8%a7%a3%e9%87%8b%e5%92%8c%e6%9b%b4%e5%a4%9a%e4%be%8b%e5%ad%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;詳細解釋和更多例子&#xA;&lt;/h4&gt;&lt;p&gt;共變數例子：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Animal&lt;/span&gt; { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Dog&lt;/span&gt; : Animal { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IEnumerable&amp;lt;Dog&amp;gt; dogs = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;Dog&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IEnumerable&amp;lt;Animal&amp;gt; animals = dogs; &lt;span style=&#34;color:#75715e&#34;&gt;// 共變數允許這種賦值&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 使用場景&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; ProcessAnimals(IEnumerable&amp;lt;Animal&amp;gt; animals) { ... }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ProcessAnimals(dogs); &lt;span style=&#34;color:#75715e&#34;&gt;// 可以傳入 Dog 的集合&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;反變數例子：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IComparer&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; T&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; Compare(T x, T y);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IComparer&amp;lt;Animal&amp;gt; animalComparer = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; AnimalComparer();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IComparer&amp;lt;Dog&amp;gt; dogComparer = animalComparer; &lt;span style=&#34;color:#75715e&#34;&gt;// 反變數允許這種賦值&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 使用場景&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AnimalComparer&lt;/span&gt; : IComparer&amp;lt;Animal&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; Compare(Animal x, Animal y) { ... }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;List&amp;lt;Dog&amp;gt; dogs = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;Dog&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dogs.Sort(dogComparer); &lt;span style=&#34;color:#75715e&#34;&gt;// 可以使用 Animal 的比較器來比較 Dog&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;共變數和反變數的組合&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IConverter&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; TInput, &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; TOutput&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    TOutput Convert(TInput input);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IConverter&amp;lt;Animal, Dog&amp;gt; animalToDog = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; AnimalToDogConverter();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IConverter&amp;lt;Dog, Animal&amp;gt; dogToAnimal = animalToDog; &lt;span style=&#34;color:#75715e&#34;&gt;// 合法&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;限制和注意事項&#34;&gt;&lt;a href=&#34;#%e9%99%90%e5%88%b6%e5%92%8c%e6%b3%a8%e6%84%8f%e4%ba%8b%e9%a0%85&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;限制和注意事項&#xA;&lt;/h4&gt;&lt;ul&gt;&#xA;&lt;li&gt;共變數和反變數只適用於引用類型，不適用於值類型。&lt;/li&gt;&#xA;&lt;li&gt;只能用於介面和委託的定義，不能用於類別。&lt;/li&gt;&#xA;&lt;li&gt;一個類別參數不能同時標記為共變數和反變數。&lt;/li&gt;&#xA;&lt;li&gt;共變數類別參數不能用作方法參數，反變數類別參數不能用作方法返回類型。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;實際應用&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;LINQ: LINQ 大量使用共變數和反變數來提高其靈活性。&lt;/li&gt;&#xA;&lt;li&gt;事件處理：允許更靈活地處理不同類別的事件。&lt;/li&gt;&#xA;&lt;li&gt;依賴注入：在依賴注入框架中常用，提高容器的靈活性。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;性能考慮&#xA;共變數和反變數主要是編譯時特性，不會對運行時性能產生顯著影響。&#xA;總結：&#xA;共變數和反變數強大的特性，能夠提高程式碼的靈活性和可重用性。&#xA;共變數（out）允許使用更具體的類型，而反變數（in）允許使用更一般的類型。正確理解和使用這些概念可以幫助設計更靈活、更強大的 API 和框架。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Main(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;[] args)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Dog dog = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Dog(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;doggy&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IOutDog&amp;lt;Dog&amp;gt; dogProvider = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; DogProvider(dog);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IOutDog&amp;lt;Animal&amp;gt; animalProvider = dogProvider;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;{animalProvider.Value.GetName()}, {dogProvider.Value.GetName()}&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 使用基本的 AnimalSetter&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IInDog&amp;lt;Animal&amp;gt; animalSetter = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; AnimalSetter();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    animalSetter.SetValue(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Animal());&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    animalSetter.SetValue(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Dog()); &lt;span style=&#34;color:#75715e&#34;&gt;// 這也是有效的，因為 Dog 是 Animal 的子類&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 使用 DogSetter，展示反變數&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// IInDog&amp;lt;Animal&amp;gt; dogSetterAsAnimal = (IInDog&amp;lt;Animal&amp;gt;)new DogSetter();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// dogSetterAsAnimal.SetValue(new Animal()); // 注意：這在運行時可能會拋出異常，因為實際的實現期望一個 Dog&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 使用泛型實現&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IInDog&amp;lt;Dog&amp;gt; dogSetter = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; GenericAnimalSetter&amp;lt;Dog&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dogSetter.SetValue(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Dog());&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IConverter&amp;lt;Animal, Dog&amp;gt; animalToDog = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; AnimalToDogConverter();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IConverter&amp;lt;Dog, Animal&amp;gt; dogToAnimal = animalToDog; &lt;span style=&#34;color:#75715e&#34;&gt;// 合法&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Animal&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; name;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Animal(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; name = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;) =&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.name = name;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;virtual&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; GetName() =&amp;gt; name;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Dog&lt;/span&gt; : Animal&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Dog(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; name = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;) : &lt;span style=&#34;color:#66d9ef&#34;&gt;base&lt;/span&gt;(name) { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; GetName() =&amp;gt; &lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;Dog {base.GetName()}&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IOutDog&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; T&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; T : Animal&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    T Value { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DogProvider&lt;/span&gt; : IOutDog&amp;lt;Dog&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Dog Value { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; DogProvider(Dog &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;) =&amp;gt; Value = &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IInDog&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; T&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; T : Animal&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; SetValue(T &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AnimalSetter&lt;/span&gt; : IInDog&amp;lt;Animal&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; Animal &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; SetValue(Animal &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;) =&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt; = &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DogSetter&lt;/span&gt; : IInDog&amp;lt;Dog&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; Dog &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; SetValue(Dog &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;) =&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt; = &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GenericAnimalSetter&lt;/span&gt;&amp;lt;T&amp;gt; : IInDog&amp;lt;T&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; T : Animal&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; T &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; SetValue(T &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;) =&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt; = &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IConverter&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; TInput, &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; TOutput&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    TOutput Convert(TInput input);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AnimalToDogConverter&lt;/span&gt; : IConverter&amp;lt;Animal, Dog&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Dog Convert(Animal input) =&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Dog(input.GetName());&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;心得&#34;&gt;&lt;a href=&#34;#%e5%bf%83%e5%be%97&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;心得&#xA;&lt;/h3&gt;&lt;p&gt;如果編譯器告訴你錯了 就要小心是不是有什麼地方搞錯了&#xA;做 cast 時要了解自己在做什麼 不然能編譯成功也會在 runtime 時炸掉&lt;/p&gt;&#xA;&lt;h2 id=&#34;做法-23&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-23&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 23&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;使用 delegate 定義型別參數的方法約束&lt;/code&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// double[] xValues = { 0,1,2,3,4,5,6,7,8,9,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;//                 0,1,2,3,4,5,6,7,8,9,};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// double[] yValues = { 0,1,2,3,4,5,6,7,8,9,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;//                 0,1,2,3,4,5,6,7,8,9,};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// List&amp;lt;Point&amp;gt; values = new List&amp;lt;Point&amp;gt;(Zip(xValues, yValues, (x, y) =&amp;gt; new Point(x, y)));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; IEnumerable&amp;lt;TOutput&amp;gt; Zip&amp;lt;T1, T2, TOutput&amp;gt;(IEnumerable&amp;lt;T1&amp;gt; left, IEnumerable&amp;lt;T2&amp;gt; right, Func&amp;lt;T1, T2, TOutput&amp;gt; generator)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IEnumerator&amp;lt;T1&amp;gt; leftEnumerator = left.GetEnumerator();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IEnumerator&amp;lt;T2&amp;gt; rightEnumerator = right.GetEnumerator();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (leftEnumerator.MoveNext() &amp;amp;&amp;amp; rightEnumerator.MoveNext())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;yield&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; generator(leftEnumerator.Current, rightEnumerator.Current);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    leftEnumerator.Dispose();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    rightEnumerator.Dispose();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Point&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; X { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; Y { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Point(&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; x, &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; y)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        X = x;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Y = y;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Point(TextReader textReader) { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/// InputCollection&amp;lt;Point&amp;gt; points = new InputCollection&amp;lt;Point&amp;gt;((InputStream) =&amp;gt; new Point(InputStream));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;delegate&lt;/span&gt; T CreateFromStream&amp;lt;T&amp;gt;(System.IO.TextReader textReader);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;InputCollection&lt;/span&gt;&amp;lt;T&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; List&amp;lt;T&amp;gt; thingsRead = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;T&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; CreateFromStream&amp;lt;T&amp;gt; readFunc;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; InputCollection(CreateFromStream&amp;lt;T&amp;gt; readFunc)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.readFunc = readFunc;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; ReadFromStream(System.IO.TextReader textReader)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        thingsRead.Add(readFunc(textReader));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; Values =&amp;gt; thingsRead;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;做法-23-心得&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-23-%e5%bf%83%e5%be%97&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 23 心得&#xA;&lt;/h3&gt;&lt;p&gt;可以利用 這種方式，讓不同類別擁有相同介面，使用相同的方法，讓程式彈性變高&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// ForeachIn(items,(item, i) =&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// {&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;//      item.SetIcon(icon[i]);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// });&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// ForeachIn(items,(item, i) =&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// {&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;//      item.SetPosition(positions[i]);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// });&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; ForeachIn&amp;lt;T&amp;gt;(T[] arr, Action&amp;lt;T, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&amp;gt; action)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; i = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; i &amp;lt; arr.Length; i++)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        action(arr[i], i);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>Effective C# 做法 20-21</title>
            <link>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-20-21/</link>
            <pubDate>Mon, 07 Oct 2024 00:57:47 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-20-21/</guid>
            <description>&lt;h2 id=&#34;做法-20&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-20&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 20&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;以 IComparable&amp;lt;T&amp;gt; 與 IComparer&amp;lt;T&amp;gt; 實作排序關係&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;實作&#34;&gt;&lt;a href=&#34;#%e5%af%a6%e4%bd%9c&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;實作&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Customer&lt;/span&gt; : IComparable&amp;lt;Customer&amp;gt;, IComparable&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; name;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; revenue;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Customer(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.name = name;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; CompareTo(Customer other)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; name.CompareTo(other.name);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; IComparable.CompareTo(&lt;span style=&#34;color:#66d9ef&#34;&gt;object?&lt;/span&gt; obj)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (obj &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; Customer other)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.CompareTo(other);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ArgumentException(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Argument must be a Customer&amp;#34;&lt;/span&gt;, nameof(obj));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;operator&lt;/span&gt; &amp;lt;(Customer left, Customer right) =&amp;gt; left.CompareTo(right) &amp;lt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;operator&lt;/span&gt; &amp;lt;=(Customer left, Customer right) =&amp;gt; left.CompareTo(right) &amp;lt;= &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;operator&lt;/span&gt; &amp;gt;(Customer left, Customer right) =&amp;gt; left.CompareTo(right) &amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;operator&lt;/span&gt; &amp;gt;=(Customer left, Customer right) =&amp;gt; left.CompareTo(right) &amp;gt;= &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Lazy&amp;lt;RevenueComparer&amp;gt; revComp = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Lazy&amp;lt;RevenueComparer&amp;gt;(() =&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt;());&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; IComparer&amp;lt;Customer&amp;gt; RevenueCompare =&amp;gt; revComp.Value;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Comparison&amp;lt;Customer&amp;gt; CompareByRevenue =&amp;gt; (left, right) =&amp;gt; left.revenue.CompareTo(right.revenue);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;RevenueComparer&lt;/span&gt; : IComparer&amp;lt;Customer&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; Compare(Customer left, Customer right)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; left.revenue.CompareTo(right.revenue);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;使用方式&#34;&gt;&lt;a href=&#34;#%e4%bd%bf%e7%94%a8%e6%96%b9%e5%bc%8f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;使用方式&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Main(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;[] args)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 創建一些 Customer 實例&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; customers = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;Customer&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Customer(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;) ,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Customer(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Bob&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;1500&lt;/span&gt;) ,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Customer(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Charlie&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;1200&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Customer(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;David&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;800&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 1. 使用默認比較（按名稱）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    customers.Sort();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Sorted by name:&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Alice: 1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Bob: 1500&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Charlie: 1200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// David: 800&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PrintCustomers(customers);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 2. 使用運算符比較&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; alice = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Customer(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; bob = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Customer(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Bob&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Alice &amp;lt; Bob: True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Alice &amp;lt;= Bob: True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Alice &amp;gt; Bob: False&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Alice &amp;gt;= Bob: False&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;Alice &amp;lt; Bob: {alice &amp;lt; bob}&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;Alice &amp;lt;= Bob: {alice &amp;lt;= bob}&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;Alice &amp;gt; Bob: {alice &amp;gt; bob}&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;Alice &amp;gt;= Bob: {alice &amp;gt;= bob}&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 3. 使用 RevenueCompare&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    customers.Sort(Customer.RevenueCompare);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\nSorted by revenue (using RevenueCompare):&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// David: 800&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Alice: 1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Charlie: 1200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Bob: 1500&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PrintCustomers(customers);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 4. 使用 CompareByRevenue&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    customers.Sort(Customer.CompareByRevenue);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\nSorted by revenue (using CompareByRevenue):&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// David: 800&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Alice: 1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Charlie: 1200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Bob: 1500&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PrintCustomers(customers);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 5. 使用 LINQ 排序&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; sortedByName = customers.OrderBy(c =&amp;gt; c);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\nSorted by name (using LINQ):&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// lice: 1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Bob: 1500&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Charlie: 1200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// David: 800&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PrintCustomers(sortedByName);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; sortedByRevenue = customers.OrderBy(c =&amp;gt; c, Customer.RevenueCompare);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\nSorted by revenue (using LINQ and RevenueCompare):&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// David: 800&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Alice: 1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Charlie: 1200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Bob: 1500&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PrintCustomers(sortedByRevenue);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; PrintCustomers(IEnumerable&amp;lt;Customer&amp;gt; customers)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; customer &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; customers)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;{customer.ToString()}&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;做法-21&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-21&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 21&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;建構支援 Disposable 型別參數的泛型類別&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;如果你建構的泛型類別的型別參數描述的任何型別實例，你必須考慮到這些型別可能有實作 IDisposable。你必須防衛性的撰寫程式並確保這些物件離開範圍後不會洩漏資源。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IEngine&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; DoWork();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Engine&lt;/span&gt; : IEngine&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; DoWork()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello World!&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;EngineDriver1&lt;/span&gt;&amp;lt;T&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; T : IEngine, &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; GetThingsDone()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        T engine = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; T();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;using&lt;/span&gt; (engine &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; IDisposable)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            engine.DoWork();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// using (var x = new EngineDriver2&amp;lt;Engine&amp;gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// {&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;//     x.GetThingsDone();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// }&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;EngineDriver2&lt;/span&gt;&amp;lt;T&amp;gt; : IDisposable &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; T : IEngine, &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; Lazy&amp;lt;T&amp;gt; engine = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Lazy&amp;lt;T&amp;gt;(() =&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; T());&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; GetThingsDone()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;using&lt;/span&gt; (engine.Value &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; IDisposable)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            engine.Value.DoWork();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Dispose()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (engine.IsValueCreated)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; resource = engine.Value &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; IDisposable;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            resource?.Dispose();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;EngineDriver3&lt;/span&gt;&amp;lt;T&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; T : IEngine&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; T engine;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; EngineDriver3(T engine)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.engine = engine;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; GetThingsDone()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        engine.DoWork();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;若-t-沒有實作-idisposable-則此區域變數的值為-null&#34;&gt;&lt;a href=&#34;#%e8%8b%a5-t-%e6%b2%92%e6%9c%89%e5%af%a6%e4%bd%9c-idisposable-%e5%89%87%e6%ad%a4%e5%8d%80%e5%9f%9f%e8%ae%8a%e6%95%b8%e7%9a%84%e5%80%bc%e7%82%ba-null&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;若 T 沒有實作 IDisposable ，則此區域變數的值為 null&#xA;&lt;/h3&gt;&lt;p&gt;如果 T（在這個例子中是 Engine）沒有實作 IDisposable 接口，那麼 engine as IDisposable 的結果就會是 null。&#xA;這個 null 值並不會導致異常或錯誤。 using 語句被設計為可以安全地處理 null 值。當 disposable 為 null 時， using 語句簡單地不執行任何釋放資源的操作。&#xA;這就是為什麼即使 Engine 類沒有實作 IDisposable，代碼仍然可以正常運行。 using 語句在這種情況下實際上不會做任何特殊的事情，代碼會繼續執行 engine.DoWork()。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>Effective C# 做法 18-19</title>
            <link>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-18-19/</link>
            <pubDate>Sat, 28 Sep 2024 01:48:09 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-18-19/</guid>
            <description>&lt;h2 id=&#34;做法-18&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-18&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 18&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;使用泛型 &amp;amp; 定義最少與足夠的約束&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;使用泛型&#34;&gt;&lt;a href=&#34;#%e4%bd%bf%e7%94%a8%e6%b3%9b%e5%9e%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;使用泛型&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;為什麼這三組執行期都共用相同的程式&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;&amp;gt; strings = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;List&amp;lt;Stream&amp;gt; streams=newList&amp;lt;Stream&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;List&amp;lt;MyClassType&amp;gt; myClassTypes=newList&amp;lt;MyClassType&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;JIT 編譯器識別出這些類型都是引用類型，因此可以使用相同的機器代碼。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;為什麼這三組有不同的機械碼?&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt;&amp;gt; doubles = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt;&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&amp;gt; ints = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;List&amp;lt;MyStruct&amp;gt; myStructs = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;MyStruct&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CLR 為每種值類型參數生成特定的代碼，以優化性能和類型安全性。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;1-泛型類別使用-default&#34;&gt;&lt;a href=&#34;#1-%e6%b3%9b%e5%9e%8b%e9%a1%9e%e5%88%a5%e4%bd%bf%e7%94%a8-default&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 泛型類別使用 default()&#xA;&lt;/h4&gt;&lt;p&gt;在講到泛型類別使用 default() 的方法寫時，需要把 T 改成 T?，因為 Value Type 的 Default = 0，而 Reference Type 是沒有 Default，回傳的結果會是 null。&#xA;需要告訴使用者可能會回傳 null 建議還是要回傳 T?，也提高程式碼閱讀性。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; T? FirstOrDefault&amp;lt;T&amp;gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; source, Predicate&amp;lt;T&amp;gt; predicate)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; item &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; source)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (predicate(item))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; item;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;2-少了-null-確認&#34;&gt;&lt;a href=&#34;#2-%e5%b0%91%e4%ba%86-null-%e7%a2%ba%e8%aa%8d&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 少了 null 確認&#xA;&lt;/h4&gt;&lt;p&gt;原本課本的判斷，少了 null 確認&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; AreEqual(T left, T right) =&amp;gt;    left.Equals(right);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以改這種寫法，多了做法 03 的寫法，用來判斷 null。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; AreEqual&amp;lt;T&amp;gt;(T left, T right)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (left &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; T qu)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; qu.Equals(right);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; right == &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;3-使用-t&#34;&gt;&lt;a href=&#34;#3-%e4%bd%bf%e7%94%a8-t&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3. 使用 T?&#xA;&lt;/h4&gt;&lt;p&gt;使用 T? 明確表示 factory 方法可能返回 null。這增加了代碼的可讀性和意圖的清晰度。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MyClass obj1 = Factory(() =&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; MyClass { Name = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Object 1&amp;#34;&lt;/span&gt; });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(obj1.Name); &lt;span style=&#34;color:#75715e&#34;&gt;// 輸出: Object 1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 使用返回 null 的工廠方法&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MyClass obj2 = Factory&amp;lt;MyClass&amp;gt;(() =&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(obj2.Name); &lt;span style=&#34;color:#75715e&#34;&gt;// 輸出: Default Name&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;delegate&lt;/span&gt; T FactoryFunc&amp;lt;T&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; T Factory&amp;lt;T&amp;gt;(FactoryFunc&amp;lt;T?&amp;gt; factory) &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; T : &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    T? resultVal = factory();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (resultVal == &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        resultVal = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; T();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; resultVal;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;4-為什麼要盡量避免約束-newstructclass&#34;&gt;&lt;a href=&#34;#4-%e7%82%ba%e4%bb%80%e9%ba%bc%e8%a6%81%e7%9b%a1%e9%87%8f%e9%81%bf%e5%85%8d%e7%b4%84%e6%9d%9f-newstructclass&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;4. 為什麼要盡量避免約束 new()、struct、class&#xA;&lt;/h4&gt;&lt;h4 id=&#34;new-約束&#34;&gt;&lt;a href=&#34;#new-%e7%b4%84%e6%9d%9f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;new() 約束&#xA;&lt;/h4&gt;&lt;p&gt;優點：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;保證類型有無參數構造函數。&#xA;缺點：&lt;/li&gt;&#xA;&lt;li&gt;限制了類型的靈活性，排除了沒有公共無參數構造函數的類型。&lt;/li&gt;&#xA;&lt;li&gt;可能導致不必要的對象創建，影響性能。&lt;/li&gt;&#xA;&lt;li&gt;難以進行單元測試，因為無法輕易模擬或替換對象。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;struct-約束&#34;&gt;&lt;a href=&#34;#struct-%e7%b4%84%e6%9d%9f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;struct 約束&#xA;&lt;/h4&gt;&lt;p&gt;優點：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;確保類型是值類型。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;缺點：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;過度限制了類型，排除了可能同樣適用的引用類型。&lt;/li&gt;&#xA;&lt;li&gt;可能導致不必要的裝箱和拆箱操作。&lt;/li&gt;&#xA;&lt;li&gt;限制了代碼的重用性和靈活性。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;class-約束&#34;&gt;&lt;a href=&#34;#class-%e7%b4%84%e6%9d%9f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;class 約束&#xA;&lt;/h3&gt;&lt;p&gt;優點：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;確保類型是引用類型。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;缺點：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;排除了可能同樣適用的值類型。&lt;/li&gt;&#xA;&lt;li&gt;限制了代碼的通用性。&lt;/li&gt;&#xA;&lt;li&gt;可能導致不必要的堆分配。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;一般建議：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;優先使用接口約束：接口約束更靈活，能同時適用於值類型和引用類型。例如：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GenericClass&lt;/span&gt;&amp;lt;T&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; T : IComparable&amp;lt;T&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;基於行為而非類型種類進行約束：關注類型能做什麼，而不是類型是什麼。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;考慮使用泛型約束的組合：在必要時，可以組合多個接口約束來精確定義所需的功能。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;使用 default 關鍵字：代替 new()，使用 default(T) 來獲取類型的默認值。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;設計靈活的 API：避免過度約束，以增加代碼的重用性和適應性。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;考慮性能影響：某些約束（如 struct）可能導致意外的性能問題。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;總結&#34;&gt;&lt;a href=&#34;#%e7%b8%bd%e7%b5%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;總結&#xA;&lt;/h3&gt;&lt;p&gt;避免使用 new()、 struct 和 class 約束主要是為了提高代碼的靈活性、可重用性和可測試性。通過使用更通用的約束（如接口），我們可以編寫出更加靈活和強大的泛型代碼，適用於更廣泛的類型。&lt;/p&gt;&#xA;&lt;h2 id=&#34;做法-19&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-19&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 19&#xA;&lt;/h2&gt;&lt;p&gt;使用執行期型別檢查特化泛型演算法&#xA;實作&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sealed&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ReverseEnumerable&lt;/span&gt;&amp;lt;T&amp;gt; : IEnumerable&amp;lt;T&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ReverseEnumerator&lt;/span&gt; : IEnumerator&amp;lt;T&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; currentIndex = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; IList&amp;lt;T&amp;gt; collection;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; T Current =&amp;gt; collection[currentIndex];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt; IEnumerator.Current =&amp;gt; Current;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; ReverseEnumerator(List&amp;lt;T&amp;gt; collection) : &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;(collection.ToArray())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; ReverseEnumerator(IList&amp;lt;T&amp;gt; collection)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            currentIndex = collection.Count;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.collection = collection;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Dispose()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; MoveNext()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; --currentIndex &amp;gt;= &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Reset()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            currentIndex = collection.Count;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sealed&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ReverseStringEnumerator&lt;/span&gt; : IEnumerator&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; sourceSequence;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; currentIndex;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; ReverseStringEnumerator(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; source)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            sourceSequence = source;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            currentIndex = source.Length;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; Current =&amp;gt; sourceSequence[currentIndex];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt; IEnumerator.Current =&amp;gt; sourceSequence[currentIndex];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Dispose() { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; MoveNext()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; --currentIndex &amp;gt;= &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; Reset()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            currentIndex = sourceSequence.Length;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt;? sourceSequence;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; IList&amp;lt;T&amp;gt;? originalSequence;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; ReverseEnumerable(IEnumerable&amp;lt;T&amp;gt; source)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (source &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; ReverseEnumerable&amp;lt;T&amp;gt; reverseEnumerable)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            sourceSequence = reverseEnumerable;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (source &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; str)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            originalSequence = str.ToArray() &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; IList&amp;lt;T&amp;gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            originalSequence = source &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; IList&amp;lt;T&amp;gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; ReverseEnumerable(IList&amp;lt;T&amp;gt; source) : &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;((IEnumerable&amp;lt;T&amp;gt;)source)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; IEnumerator&amp;lt;T&amp;gt; GetEnumerator()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (sourceSequence &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; str)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ReverseStringEnumerator(str) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; IEnumerator&amp;lt;T&amp;gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (originalSequence == &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (sourceSequence &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; ICollection&amp;lt;T&amp;gt; source)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                originalSequence = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;T&amp;gt;(source.Count);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                originalSequence = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;T&amp;gt;(sourceSequence);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ReverseEnumerator(originalSequence);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IEnumerator IEnumerable.GetEnumerator()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; GetEnumerator();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用方式&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; StringEnumerable()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; str = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; reverseEnumerable = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ReverseEnumerable&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;&amp;gt;(str);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; c &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; reverseEnumerable)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Console.Write(c);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;/// !dlroW ,olleH&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; ListEnumerable()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&amp;gt; list = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&amp;gt;() { &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;6&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; reverseEnumerable = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ReverseEnumerable&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&amp;gt;(list);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; reverseEnumerable)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Console.Write(i);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;/// 76543210&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Console.WriteLine();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>Effective C# 做法 16-17</title>
            <link>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-16-17/</link>
            <pubDate>Sun, 22 Sep 2024 22:17:41 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-16-17/</guid>
            <description>&lt;h2 id=&#34;做法-16&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-16&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 16&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;絕不在建構元中呼叫虛擬函式&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;本章節有提到 Static Code Analyzer 工具，可以利用這些工具避免建構子中呼叫虛擬函式。&#xA;工具分別有&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Visual Studio&lt;/li&gt;&#xA;&lt;li&gt;JetBrains Rider&lt;/li&gt;&#xA;&lt;li&gt;Visual Studio + ReSharper&#xA;針對 Unity 的 Static Code Analyzer 只能用這些工具&lt;/li&gt;&#xA;&lt;li&gt;JetBrains Rider&lt;/li&gt;&#xA;&lt;li&gt;Visual Studio + ReSharper&lt;/li&gt;&#xA;&lt;li&gt;Unity + Roslyn&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;做法-17&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-17&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 17&#xA;&lt;/h2&gt;&lt;p&gt;`實作標準 Dispose 模式&lt;/p&gt;&#xA;&lt;h3 id=&#34;unmanaged-型別&#34;&gt;&lt;a href=&#34;#unmanaged-%e5%9e%8b%e5%88%a5&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Unmanaged 型別&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;sbyte、byte、short、ushort、int、uint、long、ulong、nint、nuint、char、float、double、decimal 或 bool&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;任何 enum 型別&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;任何指標型別&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Tuple 其成員皆為非受控型別&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;任何只包含非受控型別欄位的使用者定義結構型別。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;unmanaged-資源&#34;&gt;&lt;a href=&#34;#unmanaged-%e8%b3%87%e6%ba%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Unmanaged 資源&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;是否繼承 IDisposable&lt;/li&gt;&#xA;&lt;li&gt;檢查類別文件&lt;/li&gt;&#xA;&lt;li&gt;分析類別用途和功能&lt;/li&gt;&#xA;&lt;li&gt;看原始碼&lt;/li&gt;&#xA;&lt;li&gt;利用反射，查看有沒有 Finalizer，如 sadehandle&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;需要實現-idisposable-的類別&#34;&gt;&lt;a href=&#34;#%e9%9c%80%e8%a6%81%e5%af%a6%e7%8f%be-idisposable-%e7%9a%84%e9%a1%9e%e5%88%a5&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;需要實現 IDisposable 的類別&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;有 Unmanaged 資源&lt;/li&gt;&#xA;&lt;li&gt;包含 IDisposable 成員&lt;/li&gt;&#xA;&lt;li&gt;大型物件或耗資源的類別，如大型資料庫、影片、音效等&lt;/li&gt;&#xA;&lt;li&gt;長生命週期物件，如連線功能、控制器等&lt;/li&gt;&#xA;&lt;li&gt;自訂義資源管理類別&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;不需要實現-idisposable-的類別&#34;&gt;&lt;a href=&#34;#%e4%b8%8d%e9%9c%80%e8%a6%81%e5%af%a6%e7%8f%be-idisposable-%e7%9a%84%e9%a1%9e%e5%88%a5&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;不需要實現 IDisposable 的類別&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;純數據類資料&lt;/li&gt;&#xA;&lt;li&gt;無狀態工具類&lt;/li&gt;&#xA;&lt;li&gt;短生命週期的簡單物件&lt;/li&gt;&#xA;&lt;li&gt;不管理任何資源的類別&#xA;不是每的類別都蓄要繼承 IDisposable 。僅當你的類別管理 Unmanaged 資源或者包含實現 IDisposable 介面的成員，才考慮繼承 IDisposable。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;1除非你的類別直接持有-unmanaged-資源否則你不應該實作-finalizer&#34;&gt;&lt;a href=&#34;#1%e9%99%a4%e9%9d%9e%e4%bd%a0%e7%9a%84%e9%a1%9e%e5%88%a5%e7%9b%b4%e6%8e%a5%e6%8c%81%e6%9c%89-unmanaged-%e8%b3%87%e6%ba%90%e5%90%a6%e5%89%87%e4%bd%a0%e4%b8%8d%e6%87%89%e8%a9%b2%e5%af%a6%e4%bd%9c-finalizer&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1.除非你的類別直接持有 Unmanaged 資源，否則你不應該實作 finalizer&#xA;&lt;/h3&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/zh-tw/dotnet/standard/garbage-collection/implementing-dispose&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;實作 Dispose 方法&lt;/a&gt;&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>Effective C# 做法 14-15</title>
            <link>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-14-15/</link>
            <pubDate>Sat, 14 Sep 2024 23:57:56 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-14-15/</guid>
            <description>&lt;h2 id=&#34;做法-14&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-14&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 14&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;減少重複的初始化邏輯&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-建構子初始化程序讓一個建構子呼叫其他的建構子&#34;&gt;&lt;a href=&#34;#1-%e5%bb%ba%e6%a7%8b%e5%ad%90%e5%88%9d%e5%a7%8b%e5%8c%96%e7%a8%8b%e5%ba%8f%e8%ae%93%e4%b8%80%e5%80%8b%e5%bb%ba%e6%a7%8b%e5%ad%90%e5%91%bc%e5%8f%ab%e5%85%b6%e4%bb%96%e7%9a%84%e5%bb%ba%e6%a7%8b%e5%ad%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 建構子初始化程序讓一個建構子呼叫其他的建構子&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyClass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;&amp;gt; coll;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; name;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; MyClass() : &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;.Empty) { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; MyClass(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; count, &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        coll = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;&amp;gt;(count);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.name = name;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2-選擇預設參數與&#34;&gt;&lt;a href=&#34;#2-%e9%81%b8%e6%93%87%e9%a0%90%e8%a8%ad%e5%8f%83%e6%95%b8%e8%88%87&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 選擇預設參數與&#xA;&lt;/h3&gt;&lt;p&gt;選擇預設參數與使用多個建構子多載之間需要權衡考量，建議是不超過 3 個，超過時可以考慮使用一個類別當初始化類別使用。一般來說應該偏好預設值而非多載建構子。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3-繼承類別不能修改父類別中宣告為-readonly-的欄位&#34;&gt;&lt;a href=&#34;#3-%e7%b9%bc%e6%89%bf%e9%a1%9e%e5%88%a5%e4%b8%8d%e8%83%bd%e4%bf%ae%e6%94%b9%e7%88%b6%e9%a1%9e%e5%88%a5%e4%b8%ad%e5%ae%a3%e5%91%8a%e7%82%ba-readonly-%e7%9a%84%e6%ac%84%e4%bd%8d&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3. 繼承類別不能修改父類別中宣告為 readonly 的欄位&#xA;&lt;/h3&gt;&lt;p&gt;readonly 欄位只能在宣告時或在定義該欄位的類別建構子中賦值。&lt;/p&gt;&#xA;&lt;h2 id=&#34;做法-15&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-15&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 15&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;避免建構不必要的物件&lt;/code&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; OnPaint(PaintEventArgs e)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;/// 劣&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    using(Font myFont = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Font(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Arial&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;12.0f&lt;/span&gt;)){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        e.Graphics.DrawString(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;, myFont, Brushes.Black, &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;推薦方式&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; Font myFont = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Font(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Arial&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;12.0f&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; OnPaint(PaintEventArgs e)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    e.Graphics.DrawString(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;, myFont, Brushes.Black, &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;1-區域變數的選擇&#34;&gt;&lt;a href=&#34;#1-%e5%8d%80%e5%9f%9f%e8%ae%8a%e6%95%b8%e7%9a%84%e9%81%b8%e6%93%87&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 區域變數的選擇&#xA;&lt;/h3&gt;&lt;p&gt;在區域變數是參考型別（實值類型就沒關係），且會在經常被呼叫的程序中使用時將它提升至成員變數。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-string-不可變的原因&#34;&gt;&lt;a href=&#34;#2-string-%e4%b8%8d%e5%8f%af%e8%ae%8a%e7%9a%84%e5%8e%9f%e5%9b%a0&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. string 不可變的原因&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;安全性：敏感資訊不會因此被修改。&lt;/li&gt;&#xA;&lt;li&gt;執行緒安全：不可變性是天然的執行緒安全。&lt;/li&gt;&#xA;&lt;li&gt;hash 一致：字典的 key 相同內容、相同的位址。&lt;/li&gt;&#xA;&lt;li&gt;字串池：.NET 優化&lt;/li&gt;&#xA;&lt;li&gt;性能優化：編譯器和運行可優化字串。&lt;/li&gt;&#xA;&lt;li&gt;API 設計簡化&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;3建構不可變的可變-builder-類別&#34;&gt;&lt;a href=&#34;#3%e5%bb%ba%e6%a7%8b%e4%b8%8d%e5%8f%af%e8%ae%8a%e7%9a%84%e5%8f%af%e8%ae%8a-builder-%e9%a1%9e%e5%88%a5&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3.建構不可變的可變 builder 類別&#xA;&lt;/h3&gt;&lt;p&gt;可以參考設計模式中的建造者模式。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>Effective C# 做法 11-13</title>
            <link>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-11-13/</link>
            <pubDate>Sat, 07 Sep 2024 13:54:06 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-11-13/</guid>
            <description>&lt;h2 id=&#34;做法-11&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-11&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 11&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;認識 .NET 資源管理&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-簡易圖示記憶體區塊的關聯圖&#34;&gt;&lt;a href=&#34;#1-%e7%b0%a1%e6%98%93%e5%9c%96%e7%a4%ba%e8%a8%98%e6%86%b6%e9%ab%94%e5%8d%80%e5%a1%8a%e7%9a%84%e9%97%9c%e8%81%af%e5%9c%96&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 簡易圖示記憶體區塊的關聯圖&#xA;&lt;/h3&gt;&lt;p&gt;&lt;img alt=&#34;img_1&#34; class=&#34;gallery-image&#34; data-flex-basis=&#34;390px&#34; data-flex-grow=&#34;162&#34; height=&#34;406&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://i.imgur.com/dfX2Obh.png&#34; width=&#34;661&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-記憶體排列物件的放置位址&#34;&gt;&lt;a href=&#34;#2-%e8%a8%98%e6%86%b6%e9%ab%94%e6%8e%92%e5%88%97%e7%89%a9%e4%bb%b6%e7%9a%84%e6%94%be%e7%bd%ae%e4%bd%8d%e5%9d%80&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 記憶體排列物件的放置位址&#xA;&lt;/h3&gt;&lt;p&gt;&lt;img alt=&#34;img_2&#34; class=&#34;gallery-image&#34; data-flex-basis=&#34;647px&#34; data-flex-grow=&#34;269&#34; height=&#34;276&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://i.imgur.com/FOmH0z0.png&#34; width=&#34;745&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;呼叫 GC 後，記憶體位置改變了，這就是記憶體回收的概念&lt;/p&gt;&#xA;&lt;p&gt;&lt;img alt=&#34;img_3&#34; class=&#34;gallery-image&#34; data-flex-basis=&#34;615px&#34; data-flex-grow=&#34;256&#34; height=&#34;294&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://i.imgur.com/JNXcMs0.png&#34; width=&#34;754&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;3-記憶體層代&#34;&gt;&lt;a href=&#34;#3-%e8%a8%98%e6%86%b6%e9%ab%94%e5%b1%a4%e4%bb%a3&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3. 記憶體層代&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;層代 0&lt;/p&gt;&#xA;&lt;p&gt;最新的層代而且包含存留較短的物件。大部分物件都會在層代 0 的記憶體回收，而且不會存留至下一個層代。記憶體回收從第 0 個層代開始。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;層代 1&lt;/p&gt;&#xA;&lt;p&gt;這個層代包含存留較短的物件，且當做較短與較長物件的緩衝區。層代 0 回收後，將壓縮可取得的物件，升階至層代 1。&lt;/p&gt;&#xA;&lt;p&gt;層代 0 已滿時，記憶體會執行回收。如果層代 0 回收沒有足夠的記憶體，才會執行層代 1 回收，再執行層代 2 回收，層代 1 回收之後有存留的物件，會提升至層代 2。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;層代 2&lt;/p&gt;&#xA;&lt;p&gt;存留較長的物件。層代 2 回收存留的物件還是回留在層代 2。&lt;/p&gt;&#xA;&lt;p&gt;最後結論就是，假如不在一開始就把物件釋放掉，最後存留至層代 1、2 時，要回收物件的時間就會越來越久，造成的記憶體效率不佳，所以要手動釋放掉物件。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/zh-tw/dotnet/standard/garbage-collection/fundamentals&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;記憶體回收的基本概念&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;4-使用-dispose-釋放資源而不是-finalizer&#34;&gt;&lt;a href=&#34;#4-%e4%bd%bf%e7%94%a8-dispose-%e9%87%8b%e6%94%be%e8%b3%87%e6%ba%90%e8%80%8c%e4%b8%8d%e6%98%af-finalizer&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;4. 使用 Dispose 釋放資源，而不是 Finalizer&#xA;&lt;/h3&gt;&lt;h2 id=&#34;做法-12&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-12&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 12&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;偏好成員初始化程序而非指派陳述&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;為什麼-initobj-會導致-boxunbox&#34;&gt;&lt;a href=&#34;#%e7%82%ba%e4%bb%80%e9%ba%bc-initobj-%e6%9c%83%e5%b0%8e%e8%87%b4-boxunbox&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;為什麼 initobj 會導致 box、unbox？&#xA;&lt;/h3&gt;&lt;p&gt;initobj 指令用於將值類型的變量初始化為其默認值，因此 initobj 不會導致 boxing 或 unboxing。&#xA;使用 initobj 時，是直接記憶體操作，不涉及對象的創建或類型的轉換。&lt;/p&gt;&#xA;&lt;p&gt;推薦用法&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyClass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;&amp;gt; labels = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;做法-13&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-13&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 13&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;對靜態類別成員進行適當的初始化&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;Singleton 初始化具有複雜的邏輯，可以在 &lt;code&gt;static&lt;/code&gt; 建構子中寫。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MySingleton&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; MySingleton instance = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; MySingleton();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; MySingleton Instance =&amp;gt; instance;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; MySingleton() { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MySingleton2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; MySingleton2 instance;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; MySingleton2()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        instance = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; MySingleton2();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; MySingleton2 Instance =&amp;gt; instance;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; MySingleton2() { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>Effective C# 做法 07-10</title>
            <link>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-07-10/</link>
            <pubDate>Wed, 28 Aug 2024 00:19:53 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-07-10/</guid>
            <description>&lt;h2 id=&#34;做法-07&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-07&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 07&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;以 delegate 表示 callback&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;可以利用 delegate 回傳 bool 當判斷或者是回傳類別等功能降低城市耦合。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;List&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&amp;gt; numbers = Enumerable.Range(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;).ToList();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; oddNumbers = numbers.Find(x =&amp;gt; x % &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; == &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; test = numbers.TrueForAll(x =&amp;gt; x &amp;lt; &lt;span style=&#34;color:#ae81ff&#34;&gt;50&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;numbers.RemoveAll(x =&amp;gt; x % &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; == &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;numbers.ForEach(x =&amp;gt; Console.WriteLine(x));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; LengthyOperation2(Func&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt;&amp;gt; pred)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; bContinue = &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; cl &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; container)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cl.DoLengthyOperation();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;foreach&lt;/span&gt; (Func&amp;lt;&lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt;&amp;gt; pr &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; pred.GetInvocationList())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                bContinue &amp;amp;= pr();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (!bContinue) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;做法-08&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-08&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 08&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;對事件叫用使用空條件運算子&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;推薦這樣寫&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; RaiseUpdate()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    counter++;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Updated?.Invoke(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;, counter);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;做法-09&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-09&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 09&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;減少 boxing 與 unboxing&lt;/code&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; i = &lt;span style=&#34;color:#ae81ff&#34;&gt;25&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt; o = i; &lt;span style=&#34;color:#75715e&#34;&gt;/// box&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(o.ToString()); &lt;span style=&#34;color:#75715e&#34;&gt;/// 25&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt; fp = &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt; fo = fp;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; ip = (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;)fo; &lt;span style=&#34;color:#75715e&#34;&gt;/// unbox&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(ip.ToString()); &lt;span style=&#34;color:#75715e&#34;&gt;/// 5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;實值類型可變轉換成 System.Object 或任何界面參考。這些轉換隱含的發生，使得尋找它們變得更為複雜。&#xA;boxing 與 unboxing 操作會在你預料之外的複製拷貝，這導致 bug。以多型方式處理實值類型也有效能成本。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;p&gt;參考類型轉換為 System.Object 或介面時的行為確實不同：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;參考類型轉換:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;參考類型本來就是從 System.Object 繼承的，所以轉換為 System.Object 或實現的介面時不需要 boxing。&lt;/li&gt;&#xA;&lt;li&gt;這種轉換只是改變了引用的類型，不會創建新的對象或複製數據。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;效能影響:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;參考類型轉換為 System.Object 或介面基本上沒有額外的效能成本。&lt;/li&gt;&#xA;&lt;li&gt;不會發生像實值類型那樣的額外記憶體分配或數據複製。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;多態性:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;參考類型本來就支持多態，不需要額外的轉換步驟。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;潛在問題:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;雖然參考類型不會遇到 boxing/unboxing 的問題，但可能會遇到其他問題，如意外的類型轉換或空引用。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;做法-10&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-10&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 10&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;只對基底類別更新使用 new 修飾詞&lt;/code&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyClass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; MagicMethod() { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;new 修飾詞必須小心使用。如果你不假思索的套用它，你會在你的物件中產生模糊的方法呼叫。這是發生在升級你的基底類別導致與你的類別衝突的特殊情況。就算在這種情況下，使用前還是要仔細思考。更重要的是，其他情況不要使用它。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>Effective C# 做法 04-06</title>
            <link>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-04-06/</link>
            <pubDate>Thu, 22 Aug 2024 21:28:59 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-04-06/</guid>
            <description>&lt;h2 id=&#34;做法-04&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-04&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 04&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;以內插字串取代 string.Format()&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;推薦這樣寫&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; name = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;test&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; height = &lt;span style=&#34;color:#ae81ff&#34;&gt;180&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; age = &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; str = &lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;userName: {name}, age: {age}, height: {height}&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;1-為什麼-mathpi-不寫-tostring-會造成-box-呢&#34;&gt;&lt;a href=&#34;#1-%e7%82%ba%e4%bb%80%e9%ba%bc-mathpi-%e4%b8%8d%e5%af%ab-tostring-%e6%9c%83%e9%80%a0%e6%88%90-box-%e5%91%a2&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 為什麼 Math.PI 不寫 ToString 會造成 box 呢?&#xA;&lt;/h3&gt;&lt;p&gt;當需要調用 ToString() 方法時，如果我們沒有顯式調用，編譯器會嘗試使用 Object.ToString()。但是，為了使用 Object 上的方法，值類型必須先轉換為 Object，這就導致了裝箱。&lt;/p&gt;&#xA;&lt;h2 id=&#34;做法-05&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-05&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 05&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;對文化特定字串偏好 FormattableString&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;推薦使用 &lt;code&gt;FormattableString&lt;/code&gt;，不會因為當地時間顯示或者數字的顯示有所差異。double 的小數點會是＂.＂；如果再歐洲會是顯示＂,＂。&lt;/p&gt;&#xA;&lt;h2 id=&#34;做法-06&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-06&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 06&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;避免字串型別 API&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;使用 &lt;code&gt;nameof&lt;/code&gt; 運算子時，任何對於屬性名稱的改變都會正確的反應在用於事件參數的字串中。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; name; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt; != name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            name = &lt;span style=&#34;color:#66d9ef&#34;&gt;value&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            PropertyChanged?.Invoke(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; PropertyChangedEventArgs(nameof(Name)));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>Effective C# 做法 01-03</title>
            <link>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-01-03/</link>
            <pubDate>Sat, 17 Aug 2024 23:09:29 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/effective-c%23-%E5%81%9A%E6%B3%95-01-03/</guid>
            <description>&lt;h2 id=&#34;做法-01&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-01&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 01&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;偏好隱含型別的區域變數&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;參考書籍提到的最後一段&lt;/p&gt;&#xA;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;簡單說，除非開者（包括以後的你）必須看到型別宣告才能理解程式，否則就使用 var 宣告區域變數。這個做法的標題是＂偏好＂而不是＂總是＂。我建議明確的宣告所有數值型別（int、float、double 與其他）而不要使用 var 宣告。其他東西就是用 var。多打幾個字 - 明確的宣告型別 - 不會提升行別安全或改善可讀性。如果挑錯宣告型別，你可能會造成編譯器本來能夠避免的低效率。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;做法-02&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-02&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 02&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;偏好 readonly 而非 const&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;必須在編譯期確定的值必須使用 const：屬性參數、switch case 標籤與 enum 定義，以及少數部會在版本間變化的數值。其餘狀況則傾向以 readonly 常數提升彈性。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;h3 id=&#34;1-const-使用建議&#34;&gt;&lt;a href=&#34;#1-const-%e4%bd%bf%e7%94%a8%e5%bb%ba%e8%ad%b0&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. const 使用建議&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;對於在編譯時就能確定且永不改變的值&lt;/li&gt;&#xA;&lt;li&gt;適用於基本數據類型（int、float、bool 等）和字符串&lt;/li&gt;&#xA;&lt;li&gt;效能略優於 readonly，因為它是編譯時常量&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2-readonly-使用建議&#34;&gt;&lt;a href=&#34;#2-readonly-%e4%bd%bf%e7%94%a8%e5%bb%ba%e8%ad%b0&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. readonly 使用建議&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;對於運行時才能確定值的情況&lt;/li&gt;&#xA;&lt;li&gt;可用於任何數據類型，包括引用類型和複雜類型&lt;/li&gt;&#xA;&lt;li&gt;允許在構造函數中賦值&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;選擇指南&#34;&gt;&lt;a href=&#34;#%e9%81%b8%e6%93%87%e6%8c%87%e5%8d%97&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;選擇指南&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;如果值在編譯時就能確定，且是基本類型或字符串，優先使用 const。&lt;/li&gt;&#xA;&lt;li&gt;如果是引用類型或需要在運行時計算的值，使用 readonly。&lt;/li&gt;&#xA;&lt;li&gt;如果需要在不同的構造函數中賦予不同的值，使用 readonly。&lt;/li&gt;&#xA;&lt;li&gt;對於靜態成員，如果符合 const 的條件，優先使用 const；否則使用 static readonly。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;做法-03&#34;&gt;&lt;a href=&#34;#%e5%81%9a%e6%b3%95-03&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;做法 03&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;偏好 is 或 as 運算子而非型別轉換&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;推薦這樣寫&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Csharp&#34; data-lang=&#34;Csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt; o = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; MyType();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/// 不推薦&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; t = (MyType)o;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/// 推薦&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (o &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; MyType myType)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    myType.Do();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;/// do samething ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>C# 淺複製與深複製</title>
            <link>https://wenrong-nexus.com/posts/c%23-%E6%B7%BA%E8%A4%87%E8%A3%BD%E8%88%87%E6%B7%B1%E8%A4%87%E8%A3%BD/</link>
            <pubDate>Sat, 22 Jun 2024 19:02:04 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/c%23-%E6%B7%BA%E8%A4%87%E8%A3%BD%E8%88%87%E6%B7%B1%E8%A4%87%E8%A3%BD/</guid>
            <description>&lt;h2 id=&#34;前言&#34;&gt;&lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;前言&#xA;&lt;/h2&gt;&lt;p&gt;之前有講到 &lt;a class=&#34;link&#34; href=&#34;../csharpvaluetypereferencetype&#34; &gt;C# Value Type、Reference Type 的差異&lt;/a&gt;，現在來講一下淺複製（Shallow Copy）與深複製（Deep Copy）。&lt;/p&gt;&#xA;&lt;h2 id=&#34;淺複製&#34;&gt;&lt;a href=&#34;#%e6%b7%ba%e8%a4%87%e8%a3%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;淺複製&#xA;&lt;/h2&gt;&lt;p&gt;將原有物件的欄位依照其型別來複製，Value Type 欄位複製其數值到另一個空間，Reference Type 欄位則是複製其參考到另一個空間，因此此兩物件的 Reference Type 都是參考到同一 instance。&lt;/p&gt;&#xA;&lt;h3 id=&#34;淺複製方式&#34;&gt;&lt;a href=&#34;#%e6%b7%ba%e8%a4%87%e8%a3%bd%e6%96%b9%e5%bc%8f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;淺複製方式&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C#&#34; data-lang=&#34;C#&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Address&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Street = &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;.Empty;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; City = &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;.Empty;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Person&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Name = &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;.Empty;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; Age = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Address Address = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Address();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Person ShallowCopy()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; (Person)&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.MemberwiseClone();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C#&#34; data-lang=&#34;C#&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Person origin = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Person()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Name = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Sam&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Age = &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Address = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Address()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Street = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;123 Main St&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        City = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Anytown&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Person copy = origin.ShallowCopy();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;copy.Name = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;John&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;copy.Age = &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;copy.Address.Street = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;456 Main St&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;copy.Address.City = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Taiwan&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Shallow Copy&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Origin: Sam, 20, 456 Main St, Taiwan&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;Origin: {origin.Name}, {origin.Age}, {origin.Address.Street}, {origin.Address.City}&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Copy: John, 30, 456 Main St, Taiwan&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;Copy: {copy.Name}, {copy.Age}, {copy.Address.Street}, {copy.Address.City}&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;輸出結果&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;Origin: Sam, 20, 456 Main St, Taiwan&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;Copy: John, 30, 456 Main St, Taiwan&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;Name&lt;/code&gt; 是 String，可是沒有跟著改變，可以先看&lt;a class=&#34;link&#34; href=&#34;../csharpreferencetypestring&#34; &gt;C# Reference Type String&lt;/a&gt;這篇。&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;Age&lt;/code&gt; 是 int，也是 Value Type，所以會改變。&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;Address&lt;/code&gt; 是 class 是 Reference Type，因為淺複製的關係導致他們（Origin、Copy）有一起改變&lt;/p&gt;&#xA;&lt;h2 id=&#34;深複製&#34;&gt;&lt;a href=&#34;#%e6%b7%b1%e8%a4%87%e8%a3%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;深複製&#xA;&lt;/h2&gt;&lt;p&gt;ValueType 與&lt;code&gt;淺複製&lt;/code&gt;相同，主要差異是&lt;code&gt;深複製&lt;/code&gt;的 Reference Type 欄位會產生新的 instance，所以其倆欄位是參考到不同 instance 的。&lt;/p&gt;&#xA;&lt;h3 id=&#34;深複製方式&#34;&gt;&lt;a href=&#34;#%e6%b7%b1%e8%a4%87%e8%a3%bd%e6%96%b9%e5%bc%8f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;深複製方式&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C#&#34; data-lang=&#34;C#&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Address&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Street = &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;.Empty;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; City = &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;.Empty;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Person&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; Name = &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;.Empty;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; Age = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Address Address = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Address();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Person DeepCopy()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Person clone = (Person)&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.MemberwiseClone();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        clone.Address = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Address&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Street = &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.Address.Street,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            City = &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.Address.City&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; clone;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C#&#34; data-lang=&#34;C#&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Person origin = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Person()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Name = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Sam&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Age = &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Address = &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Address()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Street = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;123 Main St&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        City = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Anytown&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Person copy = origin.DeepCopy();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;copy.Name = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;John&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;copy.Age = &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;copy.Address.Street = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;456 Main St&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;copy.Address.City = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Taiwan&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Shallow Copy&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Origin: Sam, 20, 123 Main St, Anytown&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;Origin: {origin.Name}, {origin.Age}, {origin.Address.Street}, {origin.Address.City}&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Copy: John, 30, 456 Main St, Taiwan&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(&lt;span style=&#34;color:#e6db74&#34;&gt;$&amp;#34;Copy: {copy.Name}, {copy.Age}, {copy.Address.Street}, {copy.Address.City}&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Origin: Sam, 20, 123 Main St, Anytown&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;Copy: John, 30, 456 Main St, Taiwan&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;與淺複製的差異，深複製的 &lt;code&gt;Address&lt;/code&gt; 欄位也會產生新的 instance，在修改 &lt;code&gt;copy.Address&lt;/code&gt; 時，不會影響到 &lt;code&gt;origin.Address&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;參考連結&#34;&gt;&lt;a href=&#34;#%e5%8f%83%e8%80%83%e9%80%a3%e7%b5%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;參考連結&#xA;&lt;/h2&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://dotblogs.com.tw/lazycodestyle/2016/06/18/183737&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;C# 複製物件的方式比較&lt;/a&gt;&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>C# Reference Type String</title>
            <link>https://wenrong-nexus.com/posts/c%23-reference-type-string/</link>
            <pubDate>Sat, 22 Jun 2024 17:40:52 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/c%23-reference-type-string/</guid>
            <description>&lt;h2 id=&#34;前言&#34;&gt;&lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;前言&#xA;&lt;/h2&gt;&lt;p&gt;之前有提到 &lt;a class=&#34;link&#34; href=&#34;../csharpvaluetypereferencetype&#34; &gt;C# Value Type、Reference Type 的差異&lt;/a&gt;，提到 String 是 Reference Type，可是在使用時卻很像 Value Type。&lt;/p&gt;&#xA;&lt;h3 id=&#34;比較值&#34;&gt;&lt;a href=&#34;#%e6%af%94%e8%bc%83%e5%80%bc&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;比較值&#xA;&lt;/h3&gt;&lt;p&gt;Value Type 以 &lt;code&gt;int&lt;/code&gt; 為舉例&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; a = &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; b = a;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a = &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(a == b); &lt;span style=&#34;color:#75715e&#34;&gt;// 輸出: false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;b&lt;/code&gt; 並沒有隨著 &lt;code&gt;a&lt;/code&gt; 改變，看得出 int 是 Value Type。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; str1 = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;abc&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; str2 = str1;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;str1 = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;def&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(str1 == str2); &lt;span style=&#34;color:#75715e&#34;&gt;// 輸出:  false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;修改 str1 卻沒有影響到 str2，所以會覺得 string 也是 Value Type(?)。&lt;/p&gt;&#xA;&lt;h3 id=&#34;比較地址&#34;&gt;&lt;a href=&#34;#%e6%af%94%e8%bc%83%e5%9c%b0%e5%9d%80&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;比較地址&#xA;&lt;/h3&gt;&lt;p&gt;使用 &lt;code&gt;object.ReferenceEquals&lt;/code&gt; 來比較，假如是 Value Type，則會輸出 &lt;code&gt;false&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; a = &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; b = &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(&lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt;.ReferenceEquals(a, b)); &lt;span style=&#34;color:#75715e&#34;&gt;// 輸出: false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;int&lt;/code&gt; 確實是 Value Type，所以會輸出 false。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; str1 = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;abc&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; str2 =  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;abc&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(&lt;span style=&#34;color:#66d9ef&#34;&gt;object&lt;/span&gt;.ReferenceEquals(str1, str2)); &lt;span style=&#34;color:#75715e&#34;&gt;// 輸出: true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;比較結果為 true，假如 String 是 Value Type，應該會與 int 的結果一樣會是 false。&lt;/p&gt;&#xA;&lt;p&gt;也就是 String 其實是 Reference Type。&lt;/p&gt;&#xA;&lt;h2 id=&#34;string-為什麼是-reference-type&#34;&gt;&lt;a href=&#34;#string-%e7%82%ba%e4%bb%80%e9%ba%bc%e6%98%af-reference-type&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;String 為什麼是 Reference Type&#xA;&lt;/h2&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.csdn.net/daigualu/article/details/59096659&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;.NET 框架-string 是 value or reference type?&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;這裡面提到兩點&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;String 對象，若值相同，則其引用地址相同。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;String 對象，若值不等，則其引用地址不等。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; str1 = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;abc&amp;#34;&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;//str1指向記憶體位置 addressA 為 abc&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; str2 = str1; &lt;span style=&#34;color:#75715e&#34;&gt;//str2指向記憶體位置 addressA&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;str1 = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;def&amp;#34;&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;//str1新指向記憶體位置 addressB 為 def&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Console.WriteLine(str1 == str2); &lt;span style=&#34;color:#75715e&#34;&gt;// 輸出:  false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;string-特點&#34;&gt;&lt;a href=&#34;#string-%e7%89%b9%e9%bb%9e&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;String 特點&#xA;&lt;/h2&gt;&lt;p&gt;String 特點就是具有不可變性（immutable），一旦 new String 在記憶體(managed heap)上為它分配一塊連續記憶體空間，我們將不能以任何方式對這個 String 進行修改。所有對這個 String 進行各項操作而返回的 String，實際上是另一個重新 new 的 String，其本身並不會產生任何變化。&lt;/p&gt;&#xA;&lt;h3 id=&#34;string-效能如何&#34;&gt;&lt;a href=&#34;#string-%e6%95%88%e8%83%bd%e5%a6%82%e4%bd%95&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;String 效能如何？&#xA;&lt;/h3&gt;&lt;p&gt;從上面就可以知道 String 有不可變性，一旦創建了就不能修改值，每次修改 String 都會產生一個新的 String，所以 String 效能比較低。&lt;/p&gt;&#xA;&lt;p&gt;所以需要經常性操作 String 可以考慮使用 &lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/zh-tw/dotnet/api/system.text.stringbuilder?view=net-8.0&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;StringBuilder&lt;/a&gt;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;結論&#34;&gt;&lt;a href=&#34;#%e7%b5%90%e8%ab%96&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;結論&#xA;&lt;/h2&gt;&lt;p&gt;來自 ChatGPT 的解釋&lt;/p&gt;&#xA;&lt;p&gt;C# String 有以下特性：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;String 有不可變性：一旦創建 string，它的內容就不能被改變。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;賦值操作的實際行為：當執行 &lt;code&gt;str = &amp;quot;abc&amp;quot;&lt;/code&gt; 時，實際上是創建了一個新的 string 對象，而不是修改原有的對象。然後，變量 &lt;code&gt;str&lt;/code&gt; 被重新指向這個新對象。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;為什麼 str2 不變：當執行 &lt;code&gt;string str2 = str1&lt;/code&gt; 時，str1 和 str2 確實指向了同一個對象。但是當 str1 被賦予新值時，它指向了一個新對象，而 str2 仍然指向原來的對象。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;值類型的行為：這種行為看起來很像值類型，但 string 仍然是引用類型。這是因為 string 的不可變性和特殊的內存管理方式。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;性能和內存管理：這種設計有助於提高性能和簡化內存管理，特別是在字符串被廣泛使用的情況下。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;字符串池（String Interning）：C#使用字符串池來優化內存使用。相同的字符串字面量會指向內存中的同一位置。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;這種行為是 C# 語言設計的一個特點，旨在結合引用類型的靈活性和值類型的一些優勢。它可能看起來有點反直覺，但在實際使用中通常是有益的。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>C# Class 和 Struct 選擇</title>
            <link>https://wenrong-nexus.com/posts/c%23-class-%E5%92%8C-struct-%E9%81%B8%E6%93%87/</link>
            <pubDate>Wed, 12 Jun 2024 22:47:08 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/c%23-class-%E5%92%8C-struct-%E9%81%B8%E6%93%87/</guid>
            <description>&lt;h2 id=&#34;前言&#34;&gt;&lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;前言&#xA;&lt;/h2&gt;&lt;p&gt;之前有講到 &lt;a class=&#34;link&#34; href=&#34;../csharpvaluetypereferencetype&#34; &gt;C# Value Type、Reference Type 的差異&lt;/a&gt;，現在來講一下 Class 和 Struct 選擇。&lt;/p&gt;&#xA;&lt;p&gt;從上一篇的文章中可以知道 Class 是 Reference type，而 Struct 是 Value type。&lt;/p&gt;&#xA;&lt;h2 id=&#34;如何選擇&#34;&gt;&lt;a href=&#34;#%e5%a6%82%e4%bd%95%e9%81%b8%e6%93%87&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;如何選擇&#xA;&lt;/h2&gt;&lt;p&gt;根據&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/zh-tw/dotnet/standard/design-guidelines/choosing-between-class-and-struct&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;在類別和結構之間選擇&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;作為經驗規則，架構中大部分的類型應該為類別。 不過，在某些情況下，實值型別的特性會使它更適合使用結構。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;p&gt;可以知道其實大部分時都是使用 Class，但在某些情況下使用 Struct 會比較適合。&lt;/p&gt;&#xA;&lt;h3 id=&#34;什麼時候使用-struct&#34;&gt;&lt;a href=&#34;#%e4%bb%80%e9%ba%bc%e6%99%82%e5%80%99%e4%bd%bf%e7%94%a8-struct&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;什麼時候使用 Struct&#xA;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;如果類型的執行個體很小，且通常短期或通常內嵌在其他物件中，請考慮定義結構，而不是類別。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;除非類型具有下列所有特性，否則請「避免」定義結構：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;其以邏輯方式表示單一值，類似於基本類型 (int、double 等)。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;其執行個體大小低於 16 個位元組。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;類型為不可變，&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;而且不需要經常進行 Box。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;在所有其他情況下，您應該將類型定義為類別。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;參考連結&#34;&gt;&lt;a href=&#34;#%e5%8f%83%e8%80%83%e9%80%a3%e7%b5%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;參考連結&#xA;&lt;/h2&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://hackmd.io/@SuFrank/H1coLlCaq&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;一起學 Class and Struct (C#)&lt;/a&gt;&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>C# Value Type、Reference Type 的差異</title>
            <link>https://wenrong-nexus.com/posts/c%23-value-typereference-type-%E7%9A%84%E5%B7%AE%E7%95%B0/</link>
            <pubDate>Tue, 11 Jun 2024 22:38:53 +0800</pubDate>
            <guid>https://wenrong-nexus.com/posts/c%23-value-typereference-type-%E7%9A%84%E5%B7%AE%E7%95%B0/</guid>
            <description>&lt;h2 id=&#34;前言&#34;&gt;&lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;前言&#xA;&lt;/h2&gt;&lt;p&gt;在公司讀書會與同事討論淺複製與深複製的差異和使用時機時，聊到 Reference Type、Value Type 的不同，但是要講淺複製與深複製之前要先講 Reference Type、Value Type 的差異。&lt;/p&gt;&#xA;&lt;h2 id=&#34;value-type-有哪些&#34;&gt;&lt;a href=&#34;#value-type-%e6%9c%89%e5%93%aa%e4%ba%9b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Value Type 有哪些&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;整數的數字型別：sbyte、byte、short、ushort、int、uint、long、ulong、nint、nuint&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;浮點數值型別：float、double、decimal&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/zh-tw/dotnet/csharp/language-reference/builtin-types/numeric-conversions&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;內建數值轉換&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;bool&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;char&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;enum&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;struct&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;ref struct&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;tuples&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/zh-tw/dotnet/csharp/language-reference/builtin-types/nullable-value-types&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;可為 Null 的值類型 (C# 參考)&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;參考：&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/zh-tw/dotnet/csharp/language-reference/builtin-types/value-types&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;實值類型 (C# 參考)&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;reference-type-有哪些&#34;&gt;&lt;a href=&#34;#reference-type-%e6%9c%89%e5%93%aa%e4%ba%9b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Reference Type 有哪些&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;宣告參考型別：class、interface、delegate、record&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;內建參考類型：dynamic、object、string&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/zh-tw/dotnet/csharp/language-reference/builtin-types/nullable-reference-types&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;可為 Null 的參考型別&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;集合和陣列：集合（List、Dictionary）、陣列（int[]、string[]）&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;參考：&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/zh-tw/dotnet/csharp/language-reference/keywords/reference-types&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;參考型別 (C# 參考)&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;value-typereference-type-的差異&#34;&gt;&lt;a href=&#34;#value-typereference-type-%e7%9a%84%e5%b7%ae%e7%95%b0&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Value Type、Reference Type 的差異&#xA;&lt;/h2&gt;&lt;p&gt;根據&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/zh-tw/dotnet/standard/design-guidelines/choosing-between-class-and-struct&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;在類別和結構之間選擇&lt;/a&gt;裡的一段話，可以分出 5 點差異。&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-存放記憶體&#34;&gt;&lt;a href=&#34;#1-%e5%ad%98%e6%94%be%e8%a8%98%e6%86%b6%e9%ab%94&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 存放記憶體&#xA;&lt;/h3&gt;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;參考型別會配置在回收的堆積和記憶體上，而實值型別則會配置在堆疊上，或內嵌在包含型別上，並在堆疊回溯時或其包含類型解除配置時解除配置。&lt;/p&gt;&#xA;&lt;p&gt;因此，實值型別的配置和解除配置的成本通常比參考型別的配置和解除配置的成本更低。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;p&gt;可以得知主要是在存放的記憶體差異，因此 Value Type 配置和解除配置的成本比 Reference Type 成本更低。&lt;/p&gt;&#xA;&lt;p&gt;實值型別的配置和解除配置的成本通常比參考型別的配置和解除配置的成本更低。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-陣列&#34;&gt;&lt;a href=&#34;#2-%e9%99%a3%e5%88%97&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 陣列&#xA;&lt;/h3&gt;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;參考型別的陣列會以換行方式配置，這表示陣列元素只是位於堆積上之參考型別執行個體的參考。實值型別陣列會內嵌配置，這表示陣列元素是實值型別實際的執行個體。&lt;/p&gt;&#xA;&lt;p&gt;因此，實值型別陣列的配置和解除配置的成本會遠比參考型別陣列的配置和解除配置的成本來得低。此外，在大部分情況下，實值型別陣列會呈現較佳的參考位置。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;p&gt;Value Type 陣列的配置和解除配置成本較低，且通常在記憶體存取表現上優於 Reference Type 陣列。然而，Reference Type 陣列在處理複雜的物件或需要物件參考的情境中仍有其必要性。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3-記憶體使用量&#34;&gt;&lt;a href=&#34;#3-%e8%a8%98%e6%86%b6%e9%ab%94%e4%bd%bf%e7%94%a8%e9%87%8f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3. 記憶體使用量&#xA;&lt;/h3&gt;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;強制轉型為參考型別或其實作的其中一個介面時，實值型別會進行 Boxed。 當強制轉型回實值型別時，它們會進行 Unboxed。&lt;/p&gt;&#xA;&lt;p&gt;因為 Box 是配置在堆積上且被回收記憶體的物件，所以過多 Boxing 和 unboxing 可能會對堆積、記憶體回收行程，以及最終是應用程式的效能造成負面影響。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;p&gt;強制轉型為 Reference Type 時，Value Type 會進行 Boxed。 當強制轉型回實值型別時會進行 Unboxed，過多的 Boxed 和 Unboxed 會增加垃圾回收（GC）的負擔，從而影響應用程式效能。&lt;/p&gt;&#xA;&lt;h3 id=&#34;4-複製參考&#34;&gt;&lt;a href=&#34;#4-%e8%a4%87%e8%a3%bd%e5%8f%83%e8%80%83&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;4. 複製參考&#xA;&lt;/h3&gt;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;參考型別指派會複製參考，而實值型別指派則會複製整個值。 因此，大型參考型別的指派成本比大型實值型別的指派成本更低。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;h3 id=&#34;5-傳遞方式&#34;&gt;&lt;a href=&#34;#5-%e5%82%b3%e9%81%9e%e6%96%b9%e5%bc%8f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;5. 傳遞方式&#xA;&lt;/h3&gt;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;參考型別會以傳址方式傳遞，而實值型別則是以傳值方式傳遞。對參考型別的執行個體所做的變更會影響所有指向執行個體的參考。實值型別執行個體會在以傳值方式傳遞時複製。變更實值型別的執行個體時，它必然不會影響其任何複本。&lt;/p&gt;&#xA;&lt;p&gt;由於不會由使用者明確建立複本，而是會在傳回引數或傳回值時隱含建立，因此可以變更的實值型別可能會對許多使用者造成混淆。 因此，實值型別應該為不可變。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;p&gt;由於 Value Type 在傳遞過程中會複製，變更複本時不會影響原始值，這有時會讓使用者感到困惑，因為預期的變更並未反映在原始變數上。&lt;/p&gt;&#xA;&lt;p&gt;為了避免這種混淆，Value Type 通常應設計為不可變（immutable）。不可變的 Value Type 一旦創建，其狀態就無法改變，這樣可以確保每個複本都是一致且獨立的。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Reference Type&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;傳遞物件的記憶體地址。因此，對該物件所做的變更會影響所有持有該物件地址的參考。&lt;/p&gt;&#xA;&lt;p&gt;當 Reference Type 的物件進行變更時，因為所有指向該物件的參考都是同一個實例，所有持有該參考的變數都會受到變更影響。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Value Type&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;會複製該值並將複本傳遞給目標位置。因此，對複本的變更不會影響原始值。&lt;/p&gt;&#xA;&lt;p&gt;當傳遞 Value Type 並對其進行變更時，因為是對複本進行操作，原始實例不會受到任何影響。這意味著每個複本都是獨立的。&lt;/p&gt;&#xA;&lt;h2 id=&#34;參考連結&#34;&gt;&lt;a href=&#34;#%e5%8f%83%e8%80%83%e9%80%a3%e7%b5%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;參考連結&#xA;&lt;/h2&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://hackmd.io/@SuFrank/H1coLlCaq&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;一起學 Class and Struct&lt;/a&gt;&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;</description>
        </item><item>
            <title>Whitelist for Windows UAC</title>
            <link>https://wenrong-nexus.com/posts/whitelist-for-windows-uac/</link>
            <pubDate>Mon, 04 Nov 2019 00:00:00 +0000</pubDate>
            <guid>https://wenrong-nexus.com/posts/whitelist-for-windows-uac/</guid>
            <description>&lt;h2 id=&#34;前言&#34;&gt;&lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;前言&#xA;&lt;/h2&gt;&lt;p&gt;因為某些程式開啟時，會跳出需要系統管理員（Administrator）權限執行程式，也導致了只要是ㄧ般使用者每次開啟時都需要輸入系統管理員密碼來執行。為了ㄧ般使用者的權限問題也不能關閉 Windows UAC。 也不可能修改一般使用者的權限，所以需要讓 Windows UAC 加入此程式為白名單，這樣就不會每次都會跳出權限要求。&lt;/p&gt;&#xA;&lt;h2 id=&#34;已知限制條件&#34;&gt;&lt;a href=&#34;#%e5%b7%b2%e7%9f%a5%e9%99%90%e5%88%b6%e6%a2%9d%e4%bb%b6&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;已知限制條件&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;程式必須以 Administrator 執行&lt;/li&gt;&#xA;&lt;li&gt;一般使用者可以執行&lt;/li&gt;&#xA;&lt;li&gt;不可完全關閉 Windows UAC&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;解決方式&#34;&gt;&lt;a href=&#34;#%e8%a7%a3%e6%b1%ba%e6%96%b9%e5%bc%8f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;解決方式&#xA;&lt;/h2&gt;&lt;p&gt;根據&lt;a class=&#34;link&#34; href=&#34;https://www.taode.idv.tw/wordpress/?p=639&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;不變更 UAC 安全性，但執行程式時又不擾民的設定方式&lt;/a&gt;，可以在 Windows Regedit 新增白名單。&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Win+R 輸入 regedit 執行&lt;/li&gt;&#xA;&lt;li&gt;根據此路徑尋找 &lt;code&gt;HKEY_CURRENT_USERS\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;右鍵新增字串值，名稱為程式（exe）路徑、資料為&lt;code&gt;~ RunAsInvoker&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;c-解決方式&#34;&gt;&lt;a href=&#34;#c-%e8%a7%a3%e6%b1%ba%e6%96%b9%e5%bc%8f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;C# 解決方式&#xA;&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-CSharp&#34; data-lang=&#34;CSharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;RegEditWhiteList&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; keyName { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; root = &lt;span style=&#34;color:#e6db74&#34;&gt;@&amp;#34;Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; keyValue = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;~ RunAsInvoker&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; RegEditWhiteList(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; keyName)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.keyName = keyName;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; SendRegedit()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        RegistryKey key = Registry.CurrentUser.OpenSubKey(root, &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        key.SetValue(keyName, keyValue,RegistryValueKind.String);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        key.Close();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;github&#34;&gt;&lt;a href=&#34;#github&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/Wenrong274/UACWhitelist&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;GitHub&lt;/a&gt;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;使用方式&#34;&gt;&lt;a href=&#34;#%e4%bd%bf%e7%94%a8%e6%96%b9%e5%bc%8f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;使用方式&#xA;&lt;/h3&gt;&lt;p&gt;因為修改註冊碼是修正當前使用者的註冊碼，因此只要換使用者就需要再新增一次白名單。&lt;/p&gt;&#xA;&lt;h2 id=&#34;參考資料&#34;&gt;&lt;a href=&#34;#%e5%8f%83%e8%80%83%e8%b3%87%e6%96%99&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;參考資料&#xA;&lt;/h2&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.taode.idv.tw/wordpress/?p=639&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;不變更 UAC 安全性，但執行程式時又不擾民的設定方式&lt;/a&gt;&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;</description>
        </item></channel>
</rss>
