EddyYeh
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # dot net物件導向隨手記 ## 友善連結 曹同學筆記c# https://lavish-neighbor-2f5.notion.site/C-b7951e3fe98d43cfa47e62ac85e7ccec 曹同學筆記SQL https://lavish-neighbor-2f5.notion.site/2022-12-16-cf153fed8df7420f953297b5f405ec06 曹同學筆記c# https://lavish-neighbor-2f5.notion.site/2022-12-16-cf153fed8df7420f953297b5f405ec06 郭老師git gist.github.com/WebappAllenKuo 郭老師電子書 http://www.webapp.com.tw/default.aspx 物件導向心智圖 https://gitmind.com/app/docs/mq5xrh31 c#教學網 https://acupun.site/lecture/csharp/#chp19 ## 問體整理 > Q1.單元測試遇到外部資源(時間、資料庫、外部檔案)怎麼辦? > Q1-1單元測試遇到報表怎麼辦? > - 把DB資料刪掉,用特定資料塞到特定表單,測完再刪。 > - 外部檔案、時間外部資料盡量不要寫成dll類別庫,無法測試 > - 報表肉眼看出來,不用測。 > Q2.單元測試測試資料太長怎麼辦? > - 不是壓力測試,不必給極端條件 > Q3.方程式名稱改中文有點怪? > - 沒關係,中文才看得懂。 > Q4.底線是private的變數慣例? > - yes,同樣在class的變數名稱,(public)Name,(private)_Name > Q5.擴充方法不寫成class當公用dll? > - 擴充方法給單一特定程式使用,可繼承dll再改為特定功能。 > Q6.以ReadBook為例,why擴充方法(字串分段等功能)不寫成class? > - 架構拆兩層Core(商業核心)和Infra(基礎建設),本題的擴充方法可以寫成Infra的class。 > 參考下圖: > ![](https://i.imgur.com/9OaaF1K.png) ## 程式物件導向重構 ### 目的: 可讀性(別人看得懂)、可維護性(別人改得動)、可擴展(低耦合彈性,軟體設計理論,並基於前兩者) https://dotblogs.com.tw/hochile/2020/02/07/110529 ### 程式寫得好定義: 1. 基本60分功能沒問題,需做單元測試!功能與測試可平行開發。 2. 專案、變數、方法命名正確 3. 不要有magic number 4. 思考重用性與不變性,用類別庫-單元測試-主控台開發公用程式,與物件階層。 5. 基於SOLID規則寫程式。 6. 基於Design Pattern ### 程式的重用性 1. 用類別庫-單元測試-主控台應用程式形成 ### 變數 & 方法 & 專案命名規則 1. 物件、屬性、或者相關的都是名稱大寫開頭,欄位命名變數,等同變數:習慣小寫命名。 2. 不能有Magic Number 3. 方法定義要做什麼,須明確再Funtion名稱上 4. 專案命名:公司_專案_用途 ### 良好的註解習慣 1. 除非命名方法與屬性非常清楚,否則一律加註解。 2. bisnessRule建議一定註解 + 單元測試。 #### 註解範圍用法: - [1,10] <<< 測1<= x <= 10 - (1,10) <<< 測1< x < 10 ### SOLID原則 * 單一職責+開放封閉 => 高內聚+低耦合 * Liskov替換 => 不要亂用繼承,可思考是否用介面替換 * 介面隔離 => 用擴充方法隔開特殊案例,或繼承+介面客製類別。可參考客製化按鈕 * 依賴反轉 => 舉例責任鍊模式可以快速新增或移除規則,在責任鍊上,而非功能或主程式。 以下連結:客製化按鈕 [C#客製化按鈕](https://learn.microsoft.com/zh-tw/dotnet/api/system.windows.forms.ibuttoncontrol) [物件導向Solid原則](https://skyyen999.gitbooks.io/-study-design-pattern-in-java/content/oodPrinciple.html) ### S: Single responsibility principle(SRP) 單一職責 類別改變的原因只有一個 會計和主管要共用同一個類別,例如打考績(?),不能兩個人共用一個class ### O: Open/close principle(OCP) 開放/封閉原則 開放:可以新增功能 封閉:盡量不要動到原本現有的程式碼 高內聚低耦合 ex:舉例 顧問沒有能力存取你們的程式,只會隨身碟拿來看,告訴你怎麼改。 ex:幫忙上傳東西,結果就故障被罵 ex:顧問一天收費1萬 專業顧問 專業顧門 專業顧門口 名片 ### L: Liskov substitution principle(LSP) Liskov替換 邏輯不能錯,正常物件的繼承! 人家的method很好,New 想要的物件搶方法就好,不用繼承他。 郭台銘有錢不用認乾爹直接搶。 汽車會發出聲音,人也會發出聲音。但人不能繼承汽車 ### I: Interface Segregation Principle(ISP) 介面隔離 介面有兩個class用他 但偷懶 介面實際只有共用兩個,但寫成8個,某一個類別用不到8個,其他6個丟出例外,這種是不行的。 解決方案:發現不是每個底下類別都需要這個介面, ex:門的介面有可以鎖的方法,但廚房的砂門沒有鎖,所以不能共用門的介面,要自己再開一個 ### D: Dependency Inversion Principle(DIP) 依賴反轉 習慣用高階的呼叫低階的功能。ex購物網站的購物功能,要叫底下的會員功能a,但某天有人買購物功能,需要呼叫另外的會員系統功能b。 要新增的話改會員功能,就不用跟也要同時改購物的bug再一起 ![](https://i.imgur.com/hcBTMWH.png) ### Design Parrtern 書:針對23種問題的解法((所以沒有MVC 不容易應用書上的範例到實際程式碼 上班公司的東西都做得出來。那就該學了(約一年多)。 - 案子功能交付後,用現成案子去試designPattern。 - 一個類別可以實做很多個介面。 ## 基礎1-1: 物件導向知識學習 ### 欄位field vs 屬性property差異 1. 欄位field 外界可以存取(無法驗證),屬性property數值進來前可以驗。 2. 屬性property可以做為read only或write only。 ### 建構子 ###### 快捷鍵 prop+tab+tab 建構屬性 ctor+tab+tab 建構子 變數var 幫你猜變數型態 若無建構函數,物件會幫你建立空白建構子。 - 下圖:若有建構子,若有參數,建構時需引入,否則物件不能new一個建構子。 ![](https://i.imgur.com/gN0Z9gG.png) - 建構子要設定參數嗎?看情況,以下範例: ###### 範例 ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp3 { internal class Program { static void Main(string[] args) { //參數要寫在constructor or method? // 定義參數 string path = @"d:\temp\demo.txt"; string path2 = @"d:\temp\demo2.txt"; string content = "Hello,Allen"; string content2 = "Hello,Simon"; //參數要寫在constructor:不佳,若要換路徑刪檔案就不方便了 new FileHelper(path).Save(content); new FileHelper(path2).Save(content2); //參數要寫在method:good var helper = new FileHelperB(); helper.Save(path, content); helper.Save(path2, content2); } } public class FileHelper { public FileHelper(string fileName) { FileName = fileName; } public string FileName { get; } /// <summary> /// 將內容存檔 /// </summary> /// <param name="content"></param> public void Save(string content) { } } public class FileHelperB { public FileHelperB() { } /// <summary> /// 將內容存檔 /// </summary> /// <param name="path"></param> /// <param name="content"></param> public void Save(string path, string content) { } } } ``` #### 所有class要用到的資訊,就寫在建構函數 - 下圖:建構子是需要初始化的值,但不是所有參數,都需要先存到建構子,例如檔案存讀檔,檔案路徑就不用先存到建構屬性 ![](https://i.imgur.com/BQ6xfep.png) ### 擴充方法 #### 擴充方法是甚麼 針對內建的類別新增一個方法,原本的程式資料型態底下可用的方法都定義好了,為了客製某些功能,就用擴充方法 #### 擴充方法不寫在公用utility 針對utility要所有的人都更新,要是更新有bug,如同window更新 #### 實作:擴充方法 針對int的型別擴充 1. class 寫static 2. method寫static 3. 參數第一個加this - 下圖:擴充方法操作 ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { int price = 210; // int tax = Order.CalcTax(price); int tax = price.CalcTax(); Console.WriteLine(tax); string value = "0123456789"; string result = value.Left(4); Console.WriteLine(result); } } public static class Order { public static int CalcTax(this int price) => (int)Math.Round(price * 0.05, MidpointRounding.AwayFromZero); public static string Left(this string value, int length) { return value.Substring(0, length); } } } ``` ### 委派 委派: event, LINQ, Functional Programing(FP) #### 1.委派的宣告 簽名碼、語法糖 ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { // 簽名碼: OperationHandler(int num1, int num2); public delegate int OperationHandler(int num1, int num2); internal class Program { static void Main(string[] args) { // 語法糖:; // OperationHandler handler = new OperationHandler(Add); OperationHandler handler = Add; int result = handler(10, 4); //2 } static int Add(int n1, int n2) { return n1 + n2; } } } ``` #### 2.委派替換方程式 ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp2 { internal class Program { static void Main(string[] args) { int price = 20000; int total = new Order().CalcPromoPrice(price, CalcByTotal); Console.WriteLine(total); } static int CalcByTotal(int price) => price >= 10000 ? price - 1000 : price; static int CalcByDiscount(int price) => price * 8 / 10; //八折 } public delegate int PromoHandler(int price); public class Order { /// <summary> /// 計算優惠價 /// </summary> /// <param name="price">原始售價</param> /// <returns></returns> public int CalcPromoPrice(int price, PromoHandler handler) { return handler(price); } } } ``` #### 3.委派替換匿名函式 ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp6 { internal class Program { static void Main(string[] args) { OperationHandler addFunc = delegate(int num1, int num2){ return num1 + num2; }; addFunc = (int num1, int num2) => num1 + num2; addFunc = (num1, num2) => num1 + num2; int result = addFunc(1, 5); // 6 Console.WriteLine(result); TruncateHandler handler = (string value) => value.Substring(0, 3); handler = (value) => value.Substring(0, 3); handler = value => value.Substring(0, 3); } } public delegate string TruncateHandler(string value); public delegate int OperationHandler(int num1, int num2); } ``` #### 4.委派之匿名函式Func<> 前一個return,後兩個參數 ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp7 { internal class Program { static void Main(string[] args) { Func<int, int, int> addFunc = Add; Func<string, int, string> leftFunc = Left; Func<int, string, DateTime, int, double, string> func = xxx; Action greet = Greet; Action<int> funcDelete = DeleteMember; } static void Greet() { Console.WriteLine("Hello, world"); } static void DeleteMember(int memberId) { } static string xxx(int n1, string v1, DateTime d1, int n2, double d2) { return "AAA"; } static string Left(string value, int lenght) { return value.Substring(0, lenght); } static int Add(int num1, int num2) { return num1 + num2; } } } ``` ### 4.1微軟範例 ```csharp= // Declare a Func variable and assign a lambda expression to the // variable. The method takes a string and converts it to uppercase. Func<string, string> selector = str => str.ToUpper(); // Create an array of strings. string[] words = { "orange", "apple", "Article", "elephant" }; // Query the array and select strings according to the selector method. IEnumerable<String> aWords = words.Select(selector); // Output the results to the console. foreach (String word in aWords) Console.WriteLine(word); /* This code example produces the following output: ORANGE APPLE ARTICLE ELEPHANT */ ``` ### 4.2 老師範例 ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp8 { internal class Program { static void Main(string[] args) { int[] items = new int[] { 1,2,3,4,5,16,7,38,9,10}; // Func<int, bool> func = number => number % 2 == 0; Func<int, bool> func = number => number % 2 == 1; List<int> result = items.MyFilter(func); Console.WriteLine(result); Console.ReadLine(); } } public static class ListExts { public static List<int> MyFilter(this int[] source, Func<int, bool> func) { List<int> evenItems = new List<int>(); foreach (var item in source) { if (func(item) == true) evenItems.Add(item); } return evenItems; } } } ``` #### 5.委派替換方程式: 應用在畫三角形上 - 主程式 ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp3 { internal class Program { static void Main(string[] args) { Console.WriteLine(Triangle.Draw(5, Triangle.Left)); Console.WriteLine(); Console.WriteLine(Triangle.Draw(5, Triangle.Right)); Console.WriteLine(); Console.WriteLine(Triangle.Draw(5, Triangle.Center)); Console.WriteLine(); } } } ``` - 類別庫 ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp3 { public delegate string RowHandler(int rows, int rowIndex); public class Triangle { private static string Draw_Right(int rows, int rowIndex) =>new string('*', rowIndex + 1).PadLeft(rows, ' '); private static string Draw_Left(int rows, int rowIndex) => new string('*', rowIndex + 1); private static string Draw_Center(int rows, int rowIndex) => new string(' ', rows - rowIndex - 1) + new string('*', (rowIndex + 1) * 2 - 1); public static RowHandler Left { get { return Draw_Left; } } public static RowHandler Right=>Draw_Left; public static RowHandler Center => Draw_Center; public static string Draw(int rows, RowHandler handler) { string result = string.Empty; for (int i = 0; i < rows; i++) { result += handler(rows, i) + "\r\n"; } return result; } } } ``` ### 介面Interface #### 定義介面 ![](https://i.imgur.com/7ff3dWc.png) - 下圖: 介面有的,class一定要有,並且是public ![](https://i.imgur.com/hF9MyvM.png) ### 繼承 - 下圖: 沒有繼承就是繼承object(所以任何的物件都有方法ToString, GetType),就算是struct的父類別是valueObject,valueObject的父類別是object ![](https://i.imgur.com/bqqEgbI.png) - 下圖: class 繼承(inherit)父類別,class實作(implement)介面 ![](https://i.imgur.com/zR8nAXu.png) - 下圖: 可以快速用同樣的create的方法,確保裡面有相關屬性可以用 ![](https://i.imgur.com/85rDwmQ.png) - 下圖: 輸出輸入可以降規或者升規 ![](https://i.imgur.com/syYVMnJ.png) ### override 在子類別與父類別資料中,分出是子類別,或是父類別 ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp5 { internal class Program { static void Main(string[] args) { //Employee emp = new Employee(); //Console.WriteLine(emp.GetTitle()); //Sales emp = new Sales(); //Console.WriteLine(emp.GetTitle()); Employee[] employees = { new Employee(), new Sales() }; foreach (Employee employee in employees) { Console.WriteLine(employee.GetTitle()); } } } public class Employee { public virtual string GetTitle() => "Employee"; } public class Sales:Employee { public override string GetTitle() => "Sales"; } } ``` ### Override& 委派事件 - class寫值觸發事件:委派事件寫法順序 定義委派事件要包含傳: 1. object 2. 自定義資料形式 寫入類別庫class屬性時,set內寫執行類別庫class的方法 類別庫class的方法,「因為主程式的方法委派給類別庫方法」,所以能觸發主程式class的方法,並執行。 - 子類別方法覆寫父類別方法, protected virtual(父類別方法), protected override(子類別方法), ```csharp= using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp4 { internal class Program { static void Main(string[] args) { Member member = new Member(); member.DataChanged += Member_DataChanged; member.Name = "Allen"; Member member2 = new Member(); member2.DataChanged += Member_DataChanged; member2.Name = "Simon"; } private static void Member_DataChanged(object sender, DateTime dt) { Member member = sender as Member; Console.WriteLine("事件被觸發了,Name=" + member.Name + " @" + dt); } } public delegate void DataChangedEventHandler(object sender, DateTime dt); public class Member { public event DataChangedEventHandler DataChanged; private string _name; public string Name { get { return _name; } set { if (string.IsNullOrEmpty(value)) throw new Exception("Name不能是null"); if (value.Length > 30) throw new Exception("Name長度不能超過30"); _name = value; OnDataChanged(DateTime.Now); } } protected virtual void OnDataChanged(DateTime arg) { // raise event if (DataChanged != null) DataChanged(this, arg); } } public class VIP : Member { private string _email; public string Email { get { return _email; } set { _email = value; // raise event OnDataChanged(DateTime.Now); } } protected override void OnDataChanged(DateTime arg) { // base.OnDataChanged(); } } } ``` ### Override(覆寫) & Overload(多載) &Polymorphism(多型)的差異 覆寫(Override)是指子類別可以覆寫父類別的方法內容,使該方法擁有不同於父類別的行為。 多載(Overload)指在一個類別(class)中,定義多個名稱相同,但參數(Parameter)不同的方法(Method)。 多型(Polymorphism)是指父類別可透過子類別衍伸成多種型態,而父類別為子類別的通用型態,再透過子類別可覆寫父類別的方法來達到多型的效果,也就是同樣的方法名稱會有多種行為。 ## 基礎1-2: 類別庫 狀況: 若有一個程式,例如股票市場營業時間true or false,若有6個地方需要同一個程式,程式1貼到程式2還好,但程式2複製貼上又改了,然後有bug,程式3又需要這份code,試問要程式3要複製程式2還是程式1呢? 建議:class公用寫在*.dll檔案。 - [x] - 類別庫(*dll)的版本越低越好 ### 加入dll參考 放在bin的debug或release就可以了 建置方案就能立刻參考dll的動作 ### 註解引入   先在原方案(方案右鍵屬性> 建置)產生XML檔案,再到參考dll的程式(右鍵建置),即可引入 ![](https://i.imgur.com/qvynztm.png) ### *.dll程式庫版本控管 #### 命名習慣 更新版本的原則,前兩個版本一樣。 1.0.0 1.0.15 - 若有bug要更新,更新最後一個小版本! - 若有物件(功能)新增,更新中型的版本! - 若有.net的版本要更新或者method的版本要更新,更新大型版本! .net版本不同範例: 字串dollar sign@ stringformat$"" << .net 4.8才有 定義小版本更新bug小。 定義中版本更新後沒有用到,給客戶虛榮心提升。 定義大版本,軟體版本號不能更新。 - 其他:召回更新.dll,不要更新就好Ans:很難,別人會互相比較。 #### 實作:更新dll版本 - 到Property的Assenbly ![](https://i.imgur.com/sGozV7U.png) ## 基礎1-3: 單元測試 ### 專案命名規則 命名規則如下: > 公司名.projectName.用途 開空白方案:.net framework namespace ispan_praticeDotNet_practice ### 任何c#可以用/// 三條橫線加註解! 註解可以用xml檔註記 ### 單元測試 #### 優點 強迫自己寫易測試&優質的程式碼 開發時可以重覆測試減少開發時間 別人快速懂功能 重構程式的保護 #### 測試用邊界條件 詳情看12/15下午剛開始 #### 時間區間題目檢討:老師的版本 可以買程式重構的書來看! - 下圖:老師的解答1 ![](https://i.imgur.com/3cHBfss.png) - 下圖:老師的解答2 ![](https://i.imgur.com/cuAe4b0.png) ## 範例1. 電子書範例 ### 1. 開專案 Ispan.ReadBooks.winform (.NetFramework4.8) Ispan.ReadBooks (.NetFramework類別庫4.8) Ispan.ReadBooks.UnitTests ctrl + shift + B = 快速建置方案的快捷鍵 - 下圖:程式碼供參,每個測試記得在上面加入[Test] ![](https://i.imgur.com/APAylj4.png) - 下圖:程式碼要資料夾 & class名稱要對稱 ![](https://i.imgur.com/pW2lV8r.png) ### 2. 需要FUNCTION<<<用擴充方法(第一個功能) page = p.GetSubArray(4,6) content = page.concat(enter) ### 3. 單元測試情境(第一個功能) ### 4. 調整參數順序ValueTuple(第二個功能) - 下圖:程式碼供參 for調整參數順序(類別庫功能) ```csharp= public static class ValueTupleExtension { /// <summary> /// 確保ValueTuple的值有依照大小順序 /// </summary> /// <param name="source"></param> /// <returns></returns> public static (int, int) EnsureInOrinal(this (int begin, int end) source) { // 古時候用ref,現在比較新的版本可以用valueTuple調整參數順序 // (int begin, int end) <<< 這個是資料型別Tuple // source 等同 (source.begin, source.end) return source.begin <= source.end ? source : (source.end, source.begin); } } ``` - 下圖:程式碼供參 for調整參數順序(單元測試) ```csharp= using System; using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; using System.Threading.Tasks; using Ispan.ReadBooks.Extensions; namespace Ispan.ReadBooks.UnitTests.Extensions { internal class ValueTupleExtension { [Test] public void Ensure_順序正確_傳回原本順序() { (int, int) soure = (4, 6); (int, int) expected = (4, 6); (int, int) actual = soure.EnsureInOrinal(); Assert.AreEqual(expected, actual); } [Test] public void Ensure_順序相反_傳回相反順序() { (int, int) soure = (14, 6); (int, int) expected = (6, 14); (int, int) actual = soure.EnsureInOrinal(); Assert.AreEqual(expected, actual); } } } ``` - 下圖:用TestCase的attribute特徵項的用法,程式碼供參 for調整參數順序(單元測試) ![](https://i.imgur.com/TsTAfly.png) ### 5. 取出陣列中的字串(第3個功能) ```csharp= public static string[] GetSubArray(this string[] source, int beginIndex, int endIndex) { if (source == null || source.Length == 0) return Array.Empty<string>(); beginIndex = beginIndex.EnsureinRange(0, source.Length - 1); endIndex = endIndex.EnsureinRange(0, source.Length - 1); //若大小相反,就對調 (int Begin, int End) range = (beginIndex, endIndex).EnsureInOrinal(); beginIndex = range.Begin; endIndex = range.End; int length = endIndex - beginIndex + 1; string[] destination = new string[length]; Array.Copy(source, beginIndex, destination, 0, length); return destination; } ``` - Array.Copy的參數 ![](https://i.imgur.com/gimHBJv.png) - 改成泛型方法 ![](https://i.imgur.com/7rzhiYH.png) ### 6. 取Array每個element TO string功能(第四個功能) - 聚合函數Aggregate ```csharp= public static string Concat(this string[] source, string seperator) { if (source == null || source.Length == 0) return string.Empty; return source.Aggregate((acc, next) => acc + seperator + next); // stringArr.Concat(;) // 輸入stringArr = ["a","b","c"] // 輸出 a;b;c } ``` ### 7.為何用this 1. 偷懶,自己呼叫自己。不用打一長串的自己值 2. 區分兩個同名變數,是this還是傳入值 ## 範例2. YCD(香腸遊戲) DiceGame ![](https://i.imgur.com/icgDcsL.png) ### 0. 特殊語法筆記 #### 0.1 建構子被呼叫前的建構。用以區隔單元測試與實際函數 ```csharp= public YcdDiceGame() : this(new DefaultRandomValueProvider()) { } public YcdDiceGame(IRandomValueProvider provider) { // pre conditions if (provider == null) throw new ArgumentNullException(nameof(provider)); do { dices = DiceUtility.CreateDices(provider, 4); } while (DiceUtility.AreUnique(dices) == true); } ``` 程式碼中的 : this(new DefaultRandomValueProvider()) 是一個建構子的呼叫語法,意思是在建立新的 YcdDiceGame 物件時,會先呼叫另一個建構子,並傳入一個新建立的 DefaultRandomValueProvider 物件。這個建構子的作用是用來初始化新建立的 YcdDiceGame 物件,並且會在執行完這個建構子之後再執行這個建構子(也就是 public YcdDiceGame() : this(new DefaultRandomValueProvider()))。 #### 介面替換的方法 ```csharp= public MockRandomValueProvider(int value, params int[] others) { _numbers.Add(value); _numbers.AddRange(others); } ``` 可以用 params傳入多個 - 下圖: 前面數值大 比較結果return 正數 ![](https://i.imgur.com/mHytBbd.png) int有實作IcompareTO,所以一定有compareTo #### 寫亂數seed的用法 - 下圖: 寫亂數seed的用法 ![](https://i.imgur.com/7Zz5KXI.png) - 下圖: Tab + Tab <= 委派c# 自動產生方法 ![](https://i.imgur.com/lygSFNj.png) - 子類別無法呼叫父類別的事件,除非Virtual On+事件名稱 <= 命名委派名稱 Virtual <= 子類別有機會override改寫 ![](https://i.imgur.com/ONsOmP8.png) - 事件要帶的參數 ![](https://i.imgur.com/HxKunBL.png) ![](https://i.imgur.com/MOUzBh0.png) ## 範例3:責任鍊 ![](https://i.imgur.com/lYLlAa5.png) ## C#程式擴充工具 ### ReSharper 可以幫忙引入using,加入程式開發 ### 神秘軟體可以讓行政人員編輯前端 c#額外付出費用? ## 面試 // 會不會interface 引言:8萬應徵5萬的司機,第一句問什麼?有駕照。 一般面試公司篩選人,.net也是。 老師的問法:會不會interface? // 唬人小故事 組員買消夜給其他人,面試時沒有你其他組員會QQ,餓死 ### 面試放作品 我的作品有這個,特色,我用了甚麼技巧。 遇到甚麼困難,怎麼解決。 無腦放作品不會有人想點連結。 ### 面試題 #### 面試題:1+2+3+...+n=用梯形公式算 #### 面試題:left outer join + group by #### 面試題:取商數 a = 10/4 <<< a = 2 因為10和4都是整數,所以出來也是整數。 a =10.0/4 or a = 10/4.0 <<< 2.5 #### 面試題:空字串的3種用法 ![](https://i.imgur.com/bFbxcDW.png) ![](https://i.imgur.com/KW8HlT3.png) ```csharp= // 1樓比較好 因為每次都找同一個空字串位址 // 2樓每次都宣告一個空位址 string a = string.Empty string b = ""; ``` ## 其他小知識 ### 維護合約知識 總共10萬 1/5 簽約3萬 2/5 交付4萬 2/12 第二次交付 2/22 客戶驗收3萬,到明年2/22月前是保固期 - 若20年後要問問題,把20年的保固錢一次收齊。 - 維護時間點 若客戶到硬撐到最後一刻才肯維護費 週期照驗收那樣算的。 - 改一個文字的故事,每次改少少的,收錢5000被嫌,下次4萬。 ### 看螢幕時 眼睛要對齊螢幕上緣。頸椎壞掉56萬。 ### 故事 // 客戶買了不用 button沒有統一放在下面。 不知道網站可以放大字形,所以button跑到畫面外。 // 唬人小故事DesignPattern入門先看簡單再看難 人死掉,天使帶他去天堂&地獄 天堂:餵鴿子 地獄:沙灘排球比基尼 ### 併購故事 Lotus 123 <<< excel 影片支援,IBM買Lotus丟掉123 Access <<< 買對方的軟體,讓他不要更新 Am: Pro <<<word office裝起來就當機 c# 可以生成ios和android的app <<< 一套200萬沒人買,直接買下這家公司。 Github <<< 買下來做azure devops? skype <<< 買下來用MSN Messenger要轉skype 聊天紀錄 自訂人名都不見。 ### 換字體注意 i I l 1 B 8 0 o O ### 網路問題 網路問問題禮貌:問完不能刪 網路上回答問題:有高手會開書單 --- ###### tags: `c#筆記`

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully