(轉載)《C#高級編程》讀書筆記

  1. C#類型的取值範圍html

    名稱 CTS類型 說明 範圍
    sbyte System.SByte 8位有符號的整數 -128~127(27−27~27127−1)
    short System.Int16 16位有符號的整數 -32 768~32 767(215−215~2151215−1)
    int System.Int32 32位有符號的整數 -2 147 483 648~2 147 483 647(231−231~2311231−1)
    long System.Int64 64位有符號的整數 263−263~2631263−1
    byte System.Byte 8位無符號的整數 0~255(0~28128−1)
    ushort System.UInt16 16位無符號的整數 0~65535(0~2161216−1)
    uint System.UInt32 32位無符號的整數 0~4 294 967 295(0~2321232−1)
    ulong System.UInt64 64位無符號的整數 0~18 446 744 073 709 551 615(0~2641264−1)
  2. 訪問限制符正則表達式

    修飾符 應用於 說明
    public 全部類型或成員 任何代碼都可以訪問該項
    protected 類型和內嵌類型的全部成員 只有派生的類型可以訪問該項
    internal 全部類型或成員 只能在包含它的程序集中訪問該項
    private 類型和內嵌類型的全部成員 只能在它所屬的類型中訪問該項
    protected internal 類型和內嵌類型的全部成員 只能在包含它的程序集和派生類型的任何代碼中訪問該項
  3. C#常見的修飾符算法

    修飾符 應用於 說明
    new 函數成員 成員用相同的簽名隱藏繼承的成員
    static 全部成員 成員不做用於類的具體實例
    virtual 僅函數成員 成員能夠由派生類重寫
    abstract 僅函數成員 虛擬成員定義了成員的簽名,但沒有提供實現代碼
    override 僅函數成員 成員重寫了繼承的虛擬或抽象成員
    sealed 類、方法和屬性 對於類,不能繼承自密封類。對於屬性和方法,成員重寫已繼承的虛擬成員,但任何派生類中的任何成員都不能重寫該成員。該修飾符必須與override一塊兒使用
    extern 僅靜態[DllImport]方法 成員在外部用另外一種語言實現
  4. 結構體編程

    • 結構是值類型,不是引用類型。
    • 存儲在棧中或存儲爲內聯(inline)(若是它們是存儲在堆中的另外一個對象的一部分),其生存期的限制與簡單的數據類型同樣。
    • 結構體不支持繼承。
    • 對於結構構造函數的工做方式有一些區別。尤爲是編譯器老是提供一個無參數的默認構造函數,它是不容許替換的。
    • 使用結構,能夠指定字段如何在內存中的佈局。
    • 注意,由於結構是值類型,因此new運算符與類和其餘引用類型的工做方式不一樣。new運算符並不分配堆中的內存,而是隻調用相應的構造函數,根據傳送給它的參數初始化全部的字段。
    • 結構遵循其餘數據類型都遵循的規則:在使用前全部的元素都必須進行初始化。在結構上調用new運算符,或者給全部的字段分別賦值,結構就徹底初始化了。固然,若是結構定義爲類的成員字段,在初始化包含的對象時,該結構會自動初始化爲0。
    • 結構是會影響性能的值類型,但根據使用結構的方式,這種影響多是正面的,也多是負面的。正面的影響是爲結構分配內存時,速度很是快,由於它們將內聯或者保存在棧中。在結構超出了做用域被刪除時,速度也很快。負面影響是,只要把結構做爲參數來傳遞或者把一個結構賦予另外一個結構(如A=B,其 中A和B是結構),結構的全部內容就被複制,而對於類,則只複製引用。這樣就會有性能損失,根據結構的大小,性能損失也不一樣。注意,結構主要用於小的數據結構。但當把結構做爲參數傳遞給方法時,應把它做爲ref參數傳遞,以免性能損失————此時只傳遞告終構在內存中的地址,這樣傳遞速度就與在類中的傳遞速度同樣快了。但若是這樣作,就必須注意被調用的方法能夠改變結構的值。
    • 結構不是爲繼承設計的。這意味着:它不能從一個結構中繼承。惟一的例外是對應的結構(和C#中的其餘類型同樣)最終派生於類System.Object。所以,結構也能夠訪問System.Object的方法。在結構中,甚至能夠重寫System.Object中的方法————如重寫ToString()方法。結構的繼承鏈是:每一個結構派生自System.ValueType類,System.ValueType類又派生自System.ObjectValueType並無給Object添加任何新成員,但提供了一些更適合結構的實現方式。注意,不能爲結構提供其餘基類,每一個結構都派生自ValueType
    • 爲結構定義構造函數的方式與爲類定義構造函數的方式相同,但 不容許定義無參數的構造函數。默認構造函數把數值字段都初始化爲0,把引用類型字段初始化爲null,且老是隱式地給出,即便提供了其餘帶參數的構造函數,也是如此。提供字段的初始值也不能繞過默認構造函數。
  5. 擴展方法數組

    • 擴展方法容許改變一個類,但不須要該類的源代碼。因此使用擴展方法的情景之一是,當不知道類的源碼或者不想修改該類的源碼卻想擴展該類,就能夠用擴展方法。
    • 擴展方法是靜態方法,它是類的一部分,但實際上沒有放在類的源代碼中。
    • 擴展方法需放在靜態類中。
    • 對於擴展方法,第一個參數是要擴展的類型,它放在this關鍵字的後面。
    • 在擴展方法中,能夠訪問所擴展類型的全部共有方法和屬性。
    • 若是擴展方法與類中的某個方法同名,就歷來不會調用擴展方法。類中已有的任何實例方法優先。
  6. var關鍵字。編譯器能夠根據變量的初始化值「推斷 」 變量的類型。使用var關鍵字須要遵循的一些規則:安全

    • 變量必須初始化。不然,編譯器就沒有推斷變量類型的依據。
    • 初始化器不能爲空。
    • 初始化器必須放在表達式中。
    • 不能把初始化器設置爲一個對象,除非在初始化器中建立了一個新對象。
  7. 密封類和密封方法數據結構

    • C#容許把類和方法聲明爲sealed。對於類,這表示不能繼承該類;對於方法,這表示不能重寫該方法。
    • 在把類或方法標記爲sealed時,最可能的情形是:若是要對庫、類或本身編寫的其餘類做用域以外的類或方法進行操做,則重寫某些功能會致使代碼混亂。也能夠因商業緣由把類或方法標記爲sealed,以防第三方以違反受權協議的方式擴展該類。但通常狀況下,在把類或成員標記爲sealed時要當心,由於這麼作會嚴重限制它的使用方式。即便認爲它不能對繼承自一個類或重寫類的某個成員發揮做用,仍有可能在未來的某個時刻,有人會遇到咱們沒有預料到的情形,此時這麼作就頗有用。.Net基類庫大量使用了密封類 ,使但願從這些類中派生出本身的類的第三方開發人員沒法訪問這些類。例如,string就是一個密封類。
  8. 約束ide

    • 泛型支持的幾種約束類型:
    約束 說明
    where T : struct 對於結構約束,類型T必須是值類型
    where T : class 類約束指定類型T必須是引用類型
    where T : IFoo 指定類型T必須實現接口IFoo
    where T : Foo 指定類型T必須派生自基類Foo
    where T : new() 這是一個構造函數約束,指定類型T必須有一個默認構造函數
    where T1 : T2 這個約束也能夠指定類型T1派生自泛型類型T2。該約束也稱爲裸類型約束
    • 只能爲默認構造函數定義構造函數約束,不能爲其餘構造函數定義構造函數約束。
    • 在C#中,where子句的一個重要限制是,不能定義必須由泛型類型實現的運算符。運算符不能再借口中定義。在where子句中,只能定義基類、接口和默認構造函數。
  9. 複製數組函數

    • 若是數組的元素是值類型,調用Clone()方法就會複製全部值。如,int[] intArray1 = {1, 2}; int[] intArray2 = (int[])intArray1.Clone();其中intArray2數組的元素也變成了{1, 2}
    • 若是數組包含引用類型,則不復制元素,而只複製引用。
    • 除了使用Clone()方法以外,還可使用Array.Copy()方法建立淺表副本。
    • Clone()方法和Copy()方法有一個重要區別:Clone()方法會建立一個新數組,而Copy()方法必須傳遞階數相同且有足夠元素的已有數組。
    • 若是須要包含引用類型的數組的深層副本,就必須迭代數組並建立新對象。
  10. Array類使用QuickSort算法對數組中的元素進行排序。Array類中的Sort()方法須要數組中的元素實現IComparable接口。簡單類型(如System.String和System.Int32)已經實現了IComparable接口。佈局

  11. 元組

    • 數組合並了相同類型的對象,而元組合並了不一樣類型的對象。
    • .NET 4定義了8個泛型Tuple類和一個靜態Tuple類,不一樣泛型Tuple類支持不一樣數量的元素。例如,Tuple<T1>包含一個元素,Tuple<T1, T2>包含兩個元素,以此類推。
    • 代碼示例: 

      public class TupleExample
      {
          static void Main()
          {
              TupleExample example = new TupleExample();
              var result = example.Divide(5, 2);
              Console.WriteLine("result of division: {0}, reminder: {1}", result.Item1, result.Item2);
          }
      
          public static Tuple<int, int> Divide(int dividend, int divisor)
          {
              int result = dividend / divisor;
              int reminder = dividend % divisor;
      
              return TupleExample.Create<int, int>(result, reminder);
          }
      }

      若是元組包含項超過8個,就可使用帶8個參數的Tuple類定義。最後一個模板參數是TRest,表示必須給它傳遞一個元組,這樣就能夠建立帶任意個參數的元組了。示例:

    • var tuple = Tuple.Create<string, string, string, int, int, int, double, Tuple<int, int>>("Stephanie", "Alina", "Nagel", 2009, 6, 2, 1.37, Tuple.Create<int, int>(52, 3490));

       

  12. 運算符

    • is運算符:能夠檢查對象是否與特定的類型兼容。「兼容」表示對象是該類型或者派生自該類型。
    • as運算符:用於執行引用類型的顯示類型轉換。若是要轉換的類型與制定的類型兼容,轉換就會成功進行;若是類型不兼容,as運算符就會返回null值。
    • sizeof運算符:使用該運算符能夠肯定棧中值類型須要的長度(單位是字節);若是對於複雜類型(和非基元類型)使用該運算符,就須要把代碼寫在unsafe塊中,如:unsafe{Console.WriteLine(sizeof(Customer));}
    • 可空類型和運算符:一般可空類型與一元或二元運算符一塊兒使用時,若是其中一個操做數或兩個操做數都是null,其結果就是null。如: 
      int? a = null; 
      int? b = a + 4; // b = null 
      int? c = a * 5; // c = null
    • 空合併運算符(??):該運算符提供了一種快捷方式,能夠在處理可空類型和引用類型時表示null可能的值。這個運算符放在兩個操做數之間,第一個操做數必須是一個可空類型或者引用類型;第二個操做數必須與第一個操做數的類型相同,或者能夠隱含地轉換爲第一個操做數的類型。
  13. 比較引用類型的相等性

    • ReferenceEquals()方法:該方法是一個靜態方法,測試兩個引用是否引用類的同一個實例,特別是兩個引用是否包含內存中的相同地址。若是提供的兩個引用引用同一個對象實例,則返回true,不然返回false。可是它認爲null等於null。另外,該方法在應用於值類型時,它老是返回false,由於爲了調用這個方法,值類型須要裝箱到對象中。
    • 虛擬的Equals()方法:Equals()虛擬版本的System.Object實現代碼也能夠比較引用。但由於這個方法是虛擬的,因此能夠在本身的類中重寫它,從而按值來比較對象。特別是若是但願類的實例用做字典中的鍵,就須要重寫這個方法,以比較相關值。不然,根據重寫Object.GetHashCode()的方式,包含對象的字典類要麼不工做,要麼工做的效率很是低。在重寫Equals()方法時要注意,重寫的代碼不會拋出異常。同理,這是由於若是拋出異常,字典類就會出問題,一些在內部調用這個方法的.NET基類也可能出問題。
    • 靜態的Equals()方法:Equals()的靜態版本與其虛擬實例版本的做用相同,其區別是靜態版本帶有兩個參數,並對它們進行相等比較。這個方法能夠處理兩個對象中有一個是null的狀況,所以,若是一個對象多是null,這個方法就能夠拋出異常,提供額外保護。靜態重載版本首先要檢查它傳遞的引用是否爲null。若是他們都是null,就返回true(由於nullnull相等)。若是隻有一個引用是null,就返回false。若是兩個引用實際上引用了某個對象,它就調用Equals()的虛擬實例版本。這表示在重寫Equals()的實例版本時,其效果至關於也重寫了靜態版本。
    • 比較運算符(==):最好將比較運算符看做嚴格的值比較和嚴格的引用比較之間的中間選項。在大多數狀況下,下面的代碼表示正在比較引用:bool b = (x == y);// x, y object references
  14. 運算符重載

    • 運算符重載的聲明方式與方法相同,但operator關鍵字告訴編譯器,它其實是一個自定義的運算符重載,後面是相關運算符的實際符號,返回類型是在使用這個運算符時得到的類型。
    • 對於二元運算符(它帶兩個參數),如+-運算符,第一個參數是運算符左邊的值,第二個參數是運算符右邊的值。
    • 通常把運算符左邊的參數命名爲lhs,運算符右邊的參數命名爲rhs
    • C#要求全部的運算符重載都聲明爲publicstatic,這表示它們與它們的類或結構相關聯,而不是與某個特定實例相關聯,因此運算符重載的代碼體不能訪問非靜態類成員,也不能訪問this標識符。
    • C#語言要求成對重載比較運算符。即,若是重載了==,也就必須重載!=;不然會產生編譯錯誤。另外,比較運算符必須返回布爾類型的值。這是它們與算術運算符的根本區別。
    • 在重載==!=時,還必須重載從System.Object中繼承的Equals()和GetHashCode()方法,不然會產生一個編譯警告。緣由是Equals()方法應實現與==運算符相同類型的相等邏輯。
  15. 委託

    • 理解委託的一個要點是它們的類型安全性很是高。
    • 理解委託的一種好方式是把委託看成這樣一件事,它給方法的簽名和返回類型指定名稱。
    • Action
      • Action是無返回值的泛型委託。
      • Action表示無參,無返回值的委託
      • Action<int,string>表示有傳入參數int,string無返回值的委託
      • Action<int,string,bool>表示有傳入參數int,string,bool無返回值的委託
      • Action<int,int,int,int>表示有傳入4個int型參數,無返回值的委託
      • Action至少0個參數,至多16個參數,無返回值。
    • Func
      • Func是有返回值的泛型委託
      • Func<int>表示無參,返回值爲int的委託
      • Func<object,string,int>表示傳入參數爲objectstring返回值爲int的委託
      • Func<object,string,int>表示傳入參數爲objectstring返回值爲int的委託
      • Func<T1,T2,,T3,int>表示傳入參數爲T1,T2,T3(泛型)返回值爲int的委託
      • Func至少0個參數,至多16個參數,根據返回值泛型返回。必須有返回值,不可void
  16. Lambda表達式

    • 只要有委託參數類型的地方,就可使用Lambda表達式。或者說Lambda表達式能夠用於類型是一個委託的任意地方。
    • 若是隻有一個參數,只寫出參數名就足夠了。若是委託使用多個參數,就把參數名放在小括號中。爲了方即可以在小括號中給變量添加參數類型。
    • 若是Lambda表達式只有一條語句,在方法塊內就不須要花括號和return語句,由於編譯器會添加一條隱式return語句。
  17. 正則表達式

    • 經常使用的特定字符和轉義序列以下表:
    符 號 含 義 示 例 匹配的示例
    ^ 輸入文本的開頭 ^B B,但只能是文本中的第一個字符
    $ 輸入文本的結尾 X$ X,但只能是文本中的最後一個字符
    . 除了換行符(\n)之外的全部單個字符 i.ation isation、ization
    * 能夠重複0次或屢次的前導字符 ra*t rt、rat、raat和raaat等
    + 能夠重複1次或屢次的前導字符 ra+t rat、raat和raaat等(但不能是rt)
    ? 能夠重複0次或1次的前導字符 ra?t 只有rt和rat匹配
    \s 任何空白字符 \sa [space]a、\ta、\na(其中[space]表示空格,\t和\n都是轉移字符)
    \S 任何不是空白的字符 \SF aF、rF、cF,但不能是\tF
    \b 字邊界 ion\b 以ion結尾的任何字
    \B 不是字邊界的任意位置 \BX\B 字中間的任何X
    • 能夠把替換的字符放在方括號中,請求匹配包含這些字符。例如,[1|c]表示字符能夠是1c。在方括號中,也能夠指定一個範圍,例如[a-z]表示全部的小寫字母,[A-E]表示A~E之間的全部大寫字母(包括字母AE),[0-9]表示一個數字。若是要搜索一個整數,就能夠編寫[0-9]+
  18. 集合

    • 鏈表。LinkedList<T>是一個雙向鏈表,其元素指向它前面和後面的元素。其特色是:插入快,查找慢。
    • 有序列表。若是須要基於鍵對所需集合排序,就可使用SortedList<TKey,TValue>類,這個類按照鍵給元素排序。
    • 字典。 
      • 字典的主要特徵是能根據鍵快速查找值。也能夠自由添加和刪除元素,這點有點像List<T>類,但沒有在內存中移動後續元素的性能開銷。
      • 用做字典中鍵的類型必須重寫Object類的GetHashCode()方法。只要字典類須要肯定元素的位置,它就要調用GetHashCode()方法。GetHashCode()方法返回的int由字典用於計算在對應位置放置元素的索引。
      • 字典的性能取決於GetHashCode()方法的實現代碼。
      • 除了實現GetHashCode()方法以外,鍵類型還必須實現IEquatable<T>.Equals()方法,或重寫Object類的Equals()方法。由於不一樣的鍵對象可能返回相同的散列代碼,因此字典使用Equals()方法來比較鍵。
  19. GetHashCode()方法的實現代碼必須知足以下要求:

    • 相同的對象應老是返回相同的值。
    • 不一樣的對象能夠返回相同的值。
    • 它應執行得比較快,計算的開銷不大。
    • 它不能拋出異常。
    • 它應至少使用一個實例字段。
    • 散列代碼值應平均分佈在int能夠存儲的整個數字範圍上。
    • 散列代碼最好在對象的生存期中不發生變化。
  20. 若是爲Equals()方法提供了重寫版本,但沒有提供GetHashCode()方法的重寫版本,C#編譯器就會顯示一個編譯警告。

  21. LINQ

    • 查詢表達式必須以from子句開頭,以selectgroup子句結束。在這兩個子句之間,可使用whereorderbyjoinlet和其餘from子句。
    • LINQIEnumerable<T>接口提供了各類擴展方法,以便用戶在實現了該接口的任意集合上使用LINQ查詢。
  22. 釋放非託管的資源

    • 在定義一個類時,可使用兩種機制來自動釋放非託管的資源。這些機制經常放在一塊兒實現,由於每種機制都爲問題提供了略微不一樣的解決辦法。
    • 釋放非託管資源的兩種機制:聲明一個析構函數(或終結器);在類中實現System.IDisposable接口。
  23. 析構函數

    • 在銷燬C++對象時,其析構函數會當即運行。但因爲使用C#時垃圾回收器的工做方式,沒法肯定C#對象的析構函數合適執行。因此,不能在析構函數中放置須要在某一時刻運行的代碼,也不該使用能以任意順序對不一樣類的實例調用的析構函數。若是對象佔用了寶貴而重要的資源,應儘快釋放這些資源,此時就不能等待垃圾回收器來釋放了。
    • C#析構函數的實現會延遲對象最終從內存中刪除的時間。沒有析構函數的對象會在垃圾回收器的一次處理中從內存中刪除,但有析構函數的對象須要兩次處理才能銷燬:第一次調用析構函數時,沒有刪除對象,第二次調用才真正刪除對象。另外,運行庫使用一個線程來執行全部對象的Finalize()方法。若是頻繁使用析構函數,並且使用它們執行長時間的清理任務,對性能的影響就會很是顯著。
  24. IDisposable接口

    • 在C#中,推薦使用System.IDisposable接口替代析構函數。IDisposable接口定義了一種模式(具備語言級的支持),該模式爲釋放非託管的資源提供了肯定的機制,並避免產生析構函數固有的與垃圾回收器相關的問題。IDisposable接口聲明瞭一個Dispos()方法,它不帶參數,返回void
    • Dispose()方法的實現代碼顯式地釋放由對象直接使用的全部非託管資源,並在全部也實現IDisposable接口的封裝對象上調用Dispose()方法。這樣,Dispose()方法爲什麼時釋放非託管資源提供了精確的控制。
聲明:本文歡迎轉載和分享,可是請尊重做者的勞動成果,轉載分享時請註明出處:http://www.cnblogs.com/davidsheh/p/5236686.html 。同時,碼字實在不易,若是你以爲筆者分享的筆記對你有點用處,請順手點擊下方的推薦,謝謝!
相關文章
相關標籤/搜索