C#類型的取值范圍
訪問限制符
C#常見的修飾符
結構體
new
運算符與類和其他引用類型的工作方式不同。new
運算符並不分配堆中的內存,而是只調用相應的構造函數,根據傳送給它的參數初始化所有的字段。new
運算符,或者給所有的字段分別賦值,結構就完全初始化了。當然,如果結構定義為類的成員字段,在初始化包含的對象時,該結構會自動初始化為0。System.Object
。因此,結構也可以訪問System.Object
的方法。在結構中,甚至可以重寫System.Object
中的方法————如重寫ToString()
方法。結構的繼承鏈是:每個結構派生自System.ValueType
類,System.ValueType
類又派生自System.Object
。ValueType
並沒有給Object
添加任何新成員,但提供了一些更適合結構的實現方式。注意,不能為結構提供其他基類,每個結構都派生自ValueType
。null
,且總是隱式地給出,即使提供了其他帶參數的構造函數,也是如此。提供字段的初始值也不能繞過默認構造函數。擴展方法
this
關鍵字的後面。var
關鍵字。編譯器可以根據變量的初始化值“推斷 ” 變量的類型。使用var關鍵字需要遵循的一些規則:
密封類和密封方法
sealed
。對於類,這表示不能繼承該類;對於方法,這表示不能重寫該方法。sealed
時,最可能的情形是:如果要對庫、類或自己編寫的其他類作用域之外的類或方法進行操作,則重寫某些功能會導致代碼混亂。也可以因商業原因把類或方法標記為sealed
,以防第三方以違反授權協議的方式擴展該類。但一般情況下,在把類或成員標記為sealed
時要小心,因為這麼做會嚴重限制它的使用方式。即使認為它不能對繼承自一個類或重寫類的某個成員發揮作用,仍有可能在將來的某個時刻,有人會遇到我們沒有預料到的情形,此時這麼做就很有用。.Net基類庫大量使用了密封類 ,使希望從這些類中派生出自己的類的第三方開發人員無法訪問這些類。例如,string
就是一個密封類。約束
where
子句的一個重要限制是,不能定義必須由泛型類型實現的運算符。運算符不能再借口中定義。在where
子句中,只能定義基類、接口和默認構造函數。復制數組
Array
類使用QuickSort
算法對數組中的元素進行排序。Array
類中的Sort()方法需要數組中的元素實現IComparable
接口。簡單類型(如System.String和System.Int32)已經實現了IComparable接口。
元組
.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); } }View Code
如果元組包含項超過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));View Code
運算符
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
可能的值。這個運算符放在兩個操作數之間,第一個操作數必須是一個可空類型或者引用類型;第二個操作數必須與第一個操作數的類型相同,或者可以隱含地轉換為第一個操作數的類型。比較引用類型的相等性
true
,否則返回false
。但是它認為null
等於null
。另外,該方法在應用於值類型時,它總是返回false,因為為了調用這個方法,值類型需要裝箱到對象中。System.Object
實現代碼也可以比較引用。但因為這個方法是虛擬的,所以可以在自己的類中重寫它,從而按值來比較對象。特別是如果希望類的實例用作字典中的鍵,就需要重寫這個方法,以比較相關值。否則,根據重寫Object.GetHashCode()
的方式,包含對象的字典類要麼不工作,要麼工作的效率非常低。在重寫Equals()方法時要注意,重寫的代碼不會拋出異常。同理,這是因為如果拋出異常,字典類就會出問題,一些在內部調用這個方法的.NET
基類也可能出問題。null
的情況,因此,如果一個對象可能是null
,這個方法就可以拋出異常,提供額外保護。靜態重載版本首先要檢查它傳遞的引用是否為null
。如果他們都是null
,就返回true
(因為null
與null
相等)。如果只有一個引用是null
,就返回false
。如果兩個引用實際上引用了某個對象,它就調用Equals()的虛擬實例版本。這表示在重寫Equals()的實例版本時,其效果相當於也重寫了靜態版本。bool b = (x == y);// x, y object references
運算符重載
operator
關鍵字告訴編譯器,它實際上是一個自定義的運算符重載,後面是相關運算符的實際符號,返回類型是在使用這個運算符時獲得的類型。+
和-
運算符,第一個參數是運算符左邊的值,第二個參數是運算符右邊的值。lhs
,運算符右邊的參數命名為rhs
。public
和static
,這表示它們與它們的類或結構相關聯,而不是與某個特定實例相關聯,所以運算符重載的代碼體不能訪問非靜態類成員,也不能訪問this
標識符。==
,也就必須重載!=
;否則會產生編譯錯誤。另外,比較運算符必須返回布爾類型的值。這是它們與算術運算符的根本區別。==
和!=
時,還必須重載從System.Object
中繼承的Equals()和GetHashCode()方法,否則會產生一個編譯警告。原因是Equals()方法應實現與==
運算符相同類型的相等邏輯。委托
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>
表示傳入參數為object
, string
返回值為int的委托Func<object,string,int>
表示傳入參數為object
, string
返回值為int的委托Func<T1,T2,,T3,int>
表示傳入參數為T1
,T2
,T3
(泛型)返回值為int
的委托Func
至少0個參數,至多16個參數,根據返回值泛型返回。必須有返回值,不可void
Lambda
表達式
Lambda
表達式。或者說Lambda
表達式可以用於類型是一個委托的任意地方。Lambda
表達式只有一條語句,在方法塊內就不需要花括號和return
語句,因為編譯器會添加一條隱式return
語句。正則表達式
[1|c]
表示字符可以是1
或c
。在方括號中,也可以指定一個范圍,例如[a-z]
表示所有的小寫字母,[A-E]
表示A
~E
之間的所有大寫字母(包括字母A
和E
),[0-9]
表示一個數字。如果要搜索一個整數,就可以編寫[0-9]+
。集合
LinkedList<T>
是一個雙向鏈表,其元素指向它前面和後面的元素。其特點是:插入快,查找慢。SortedList<TKey,TValue>
類,這個類按照鍵給元素排序。List<T>
類,但沒有在內存中移動後續元素的性能開銷。int
由字典用於計算在對應位置放置元素的索引。IEquatable<T>.Equals()
方法,或重寫Object
類的Equals()方法。因為不同的鍵對象可能返回相同的散列代碼,所以字典使用Equals()方法來比較鍵。GetHashCode()方法的實現代碼必須滿足如下要求:
int
可以存儲的整個數字范圍上。如果為Equals()方法提供了重寫版本,但沒有提供GetHashCode()方法的重寫版本,C#編譯器就會顯示一個編譯警告。
LINQ
from
子句開頭,以select
或group
子句結束。在這兩個子句之間,可以使用where
、orderby
、join
、let
和其他from
子句。LINQ
為IEnumerable<T>
接口提供了各種擴展方法,以便用戶在實現了該接口的任意集合上使用LINQ
查詢。釋放非托管的資源
System.IDisposable
接口。析構函數
IDisposable接口
System.IDisposable
接口替代析構函數。IDisposable
接口定義了一種模式(具有語言級的支持),該模式為釋放非托管的資源提供了確定的機制,並避免產生析構函數固有的與垃圾回收器相關的問題。IDisposable
接口聲明了一個Dispos()方法,它不帶參數,返回void
。IDisposable
接口的封裝對象上調用Dispose()方法。這樣,Dispose()方法為何時釋放非托管資源提供了精確的控制。以上是《C#高級編程》前二十章的讀書筆記。筆記摘錄了筆者認為易忘的知識點,方便以後查閱和復習。摘抄整理過程中難免疏忽和遺漏,如有錯誤不當之處,請不吝指出,在此感激不盡!
聲明:本文歡迎轉載和分享,但是請尊重作者的勞動成果,轉載分享時請注明出處:http://hovertree.com 。同時,碼字實在不易,如果你覺得筆者分享的筆記對你有點用處,請順手點擊下方的推薦,謝謝!