1. 程式人生 > >C#基礎(learning hard 學習筆記)

C#基礎(learning hard 學習筆記)

-------------------------------------------------------------華麗分割線----------------------------------------------------------------

常用關鍵字

as:型別轉換;    

base:從派生類中訪問基類的成員;用於從派生類中訪問基類的成員,呼叫基類上已被其他方法重寫的方法。指定建立派生類例項時應呼叫的基類建構函式;從靜態方法中使用 base 關鍵字是錯誤的;除了base,訪問基類成員的另外一種方式是:顯示的型別轉換來實現。只是該方法不能為靜態方法;    

checked:對整型型別算術運算和轉換顯式啟用溢位檢查;    

decimal:表示128位資料型別,同浮點型相比,具有更高的精度和更小的範圍,適合於財務和貨幣計算;    

extern:在方法宣告中使用extern修飾符支援在外部實現方法。外部修飾符的常見方法是在使用Interop 服務調入非託管程式碼時與 DllImport 屬性一起使用;在這種情況下,該方法還必須宣告為static;[DllImport("avifil32.dll")]    public static extern void Foo();    public extern static void Fill();    

interface:可以理解為對一組方法宣告進行的統一命名,但這些方法沒有提供任何實現;通過介面,可以對方法進行統一管理,避免在每種型別中重複定

義這些方法;在介面中定義的方法不能新增任何訪問修飾符,因為介面中的方法預設為public;介面中不能包含欄位、運算子過載、示例建構函式和解構函式;  介面定義了屬性、方法和事件、索引器,這些都是介面的成員。介面只包含了成員的宣告,無實現。成員的定義是派生類的責任。介面提供了派生類應遵循的標準結構。  

internal:只能在本程式集中訪問;修飾的方法或者屬性或類,Class前面預設的修飾符就是internal,不用顯性使用;    

lock:將語句塊標記為臨界區,方法是獲取給定物件的互斥鎖,執行語句,然後釋放該鎖;

operator:過載運算子,使用者自定義轉換;

ref:是有進有出,必須先初始化;

out:是隻出不進;

abstract:用於修飾類、方法、屬性、索引器、時間,不包括欄位。 使用abstrac修飾的類,該類只能作為其他類的基類,不能例項化;內部可包含已實現的函式,使用abstract以指示方法或屬性不包含實現,必須在派生類中全部實現,不允許部分實現,否則編譯異常,除非子類也是抽象的; 抽象方法是隱式的虛擬函式,只能在抽象類中宣告;

virtual:用於修飾方法、屬性、索引器或事件宣告,並使它們可以在派生類中被重寫,也可以不重寫;和抽象方法的相同點是都用了override關鍵字進行重寫方法,不同點是抽象方法必須存在於抽象類中,而子類必須重寫,除非子類也是抽象的;

我們選擇使用虛方法實現多型還是抽象類抽象方法實現多型,取決於我們是否需要使用基類例項化的物件;其實多型就是:同一操作作用於不同的物件,可以有不同的解釋,產生不同的執行結果;允許將子類型別引用賦值給父類型別的引用,在執行時,可以通過指向父類的引用,來呼叫多種子類中實現的方法;

override:子類重寫的基方法必須是 virtual、abstract 或 override 的;當子類物件賦值給父類時,如:‘父類’p = new ‘子類’(),override呼叫子類的方法,而new呼叫父類方法。

new:隱藏;如果想在派生類定義與基類成員同名的成員,用new將基類成員隱藏起來;如果不使用new,兩個同名成員,編譯器會產生告警資訊;虛方法、實方法都可以被隱藏new,抽象方法、介面不可以被隱藏new。

params:來實現可變引數;

const:在編譯的時候就需要有確定的值,只能用於數值和字串,或者引用型別只能為null;const關鍵字可以應用於欄位或區域性變數;const是屬於類級別而不是例項物件級別,不能跟static一起使用;沒有分配記憶體,因為在編譯後,在IL程式碼中嵌入了常量值;常量在c#中是預設靜態的。只能通過類名訪問;

readonly:關鍵字只應用於欄位而不是區域性變數;我們可以在宣告或建構函式時指定readonly欄位,而不是在任何其他方法中。為Readonly欄位分配的動態記憶體,可以在我們執行時獲得值。readonly僅僅用於修飾class的欄位,不能修飾屬性;readonly既可以是類級別也可以是例項級別,它可以與static一起使用;程式執行時才會去求值;它可以是任意型別,當然可以是object,陣列,struct,它必須在建構函式或者初始化器中初始化,初始化完成之後不能被修改。通常可以定義一個readonly值為DateTime的常量。而const卻無法指定為DateTime型別。

sealed: 當對一個類應用 sealed 修飾符時,此修飾符會阻止其他類從該類繼承;sealed 修飾方法或屬性防止它們重寫特定的虛方法或虛屬性;

volatile 關鍵字指示一個欄位可以由多個同時執行的執行緒修改。宣告為 volatile 的欄位不受編譯器優化(假定由單個執行緒訪問)的限制。這樣可以確保該欄位在任何時間呈現的都是最新的值。volatile 修飾符通常用於由多個執行緒訪問但不使用 lock 語句;對訪問進行序列化的欄位。

using:在檔案頂部引用名稱空間;為名稱空間或型別定義別名;using 語句中使用的物件必須實現 IDisposable 介面。此介面提供了 Dispose 方法,該方法將釋放此物件的資源;using只能用於實現了IDisposable介面的型別;

---2----------------------------------------------------------華麗分割線----------------------------------------------------------------

1、靜態建構函式 用於初始化類中的靜態成員,在建立第一個例項或引用任何靜態成員之前,CLR都自動呼叫靜態建構函式;不能使用任何訪問修飾符;不能帶任何引數;只會執行一次;不能直接呼叫靜態建構函式;無法控制執行靜態建構函式的時機;

2、解構函式 用於類銷燬之前釋放類例項所使用的託管和非託管資源;對於大多數物件,GC會自動回收;但是對於非託管資源的物件,使用完之後,GC將執行解構函式來釋放它們;解構函式隱式的呼叫基類object的Finalize方法;不能在結構體中定義解構函式;一個類只有一個解構函式;無法繼承、過載;無法顯示呼叫,由GC自動呼叫;沒有修飾符也沒有引數;

3、索引器:當一個類包含陣列時,索引器簡化對陣列的操作;
定義:Class PP{ [修飾符] 資料型別 this[索引型別 index];{get{} set{}} }

使用:PP p = new PP(); p[0] = 1;p[1] = 2;

4、4.1結構體中不可對宣告欄位初始化;4.2類中一旦定義了一個建構函式,就不會自動生成隱式建構函式;結構體中隱式建構函式都一直存在;不能顯示定義無參建構函式;4.3在結構體的建構函式中,必須為結構體中所有欄位賦值;4.4建立結構體物件可以不使用new,但此時結構體物件中的欄位是沒有初始值的;4.5結構體不能繼承結構體或類,但可以實現介面;類不能繼承結構體;4.6類是引用型別,結構體是值型別;4.7結構體不能定義解構函式;4.8不能使用abstract和sealed修飾結構體;

---3----------------------------------------------------------華麗分割線-----------------------------------------------------------

面向物件的程式設計,靈活運用:類的封裝、繼承、多型 三大特徵;

----4---------------------------------------------------------華麗分割線-------------------------------------------------------------

1、抽象類與介面

相同點:都不能被直接例項化,都可以通過繼承實現其抽象方法。  

不同點:  介面支援多繼承;抽象類不能實現多繼承。  
介面只能定義行為;抽象類既可以定義行為,還可能提供實現。  
介面只包含方法(Method)、屬性(Property)、索引器(Index)、事件(Event)的簽名,但不能定義欄位和包含實現的方法; 
抽象類可以定義欄位、屬性、包含有實現的方法。

介面可以作用於值型別(Struct)和引用型別(Class);抽象類只能作用於引用型別。例如,Struct就可以繼承介面,而不能繼承類。

2、委託是一種安全地封裝方法的型別;它實際上是一個能夠持有對某個方法的引用的類;委託繼承於SystemMulticastDelegate型別,包含建構函式和3個方法(Invoke(用來顯式呼叫委託),IAsyncResult,EndInvoke(是兩個非同步方法));可傳參到回撥函式中,亦可直接呼叫委託;函式指標只能指向靜態函式,而委託都可以;委託在引用非靜態函式時,委託不但儲存了對函式入口指標的引用,還儲存了呼叫此函式入口的類例項的引用;

事件:是對委託的封裝,C#中的事件是一個特殊的多路廣播委託,預設有一個私有的委託型別變數,儲存對時間處理方法的引用;並提供了對私有委託訪問的方法;事件削弱了委託的功能,event在編譯器角度保護了你程式的安全,因為你只能使用+=、-= 來註冊事件了,而不能使用 = 為事件關聯方法。(在委託中還可以使用=來繫結方法,不過=是一種破壞性程式碼,不管之前是否已經繫結的有方法了,他都會將其清除);

事件的定義:訪問修飾符 event 委託型別 事件名;

事件的定義中還包含委託型別,即可以是自定義的委託型別,也可以是.NET庫中預定義的委託型別EventHandler;

-----5--------------------------------------------------------華麗分割線---------------------------------------------------------------------

1、泛型提供的程式碼重用是演算法的重用,即某個方法實現不需要考慮所操作資料的型別;

泛型類class MyClass<U>

泛型方法
public void ShowT<T>(T t){}
泛型介面
interface IMyGenericInterface<TKey,TValue>{}
泛型委託
delegate void Del<T>(T item);
泛型約束
//Compare<T>為泛型類,T為型別引數
public class Compare<T> where T : IComparable
{
public static T compareGeneric(T t1,T t2){}
}
//呼叫 Compare<int>.compareGeneric(3,4);


2、可空型別也是值型別,但是它包含null值的值型別;int? nullable = null;

int?只是一個語法糖,提供一種方便表達的形式,C#中沒有int?這個型別;int?會被編譯成Nullable<int>型別;

空合併操作符??操作符,對左右兩個操作符進行判斷:如果左邊不為null,返回左邊的數,否則返回右邊的數;可用於可空型別和引用型別;

3、lambda表示式:=>運算子(goes to),左邊是匿名方法的輸入引數,右邊是表示式或語句塊;
Func<string,int> delegatetest = txt => txt.Length;
呼叫delegatetest("ffff");

4、擴充套件方法能夠向現有型別“新增”方法,而無需建立新的派生型別,重新編譯或以其他方式修改原始型別。擴充套件方法必須是靜態方法,可以像例項方法一樣進行呼叫。且呼叫同名中實際定義的方法優先順序要高於擴充套件方法。
先說一個熟悉的內容,LINQ表示式,其實它就是擴充套件方法的一種體現。也就是對String,Int,DataRow,DataTable等這些型別的基礎上新增一個或多個方法,而不需要去修改或者編譯型別本身。擴充套件方法的書寫格式:它是在靜態類中定義了靜態方法,然後在函式第一個引數必須使用this來修飾;

那為什麼擴充套件方法沒有得到很大的推廣呢?(不足之處)

1、是靜態方法,使用不當會造成“汙染”;

2、不具有override的能力,不會過載原有的方法

3、擴充套件方法會被擴充套件類的同名方法覆蓋,所以實現擴充套件方法我們需要承擔隨時被覆蓋的風險

4、擴充套件方法不能訪問被擴充套件類的私有成員

5、擴充套件方法只能用例項來呼叫,不能像普通的靜態方法一樣使用類名呼叫;

6、只有引入擴充套件方法所在的名稱空間後,擴充套件方法才可以使用。

擴充套件方法的本質

1、將例項方法呼叫在編譯期改變為靜態類中的靜態方法呼叫,實際上,它確實擁有靜態方法所有具有的所有功能。

2、作用域是整個namespace可見的,並通過使用using namespace來匯入其他名稱空間中的擴充套件方法。

3、優先順序:現有例項方法優先順序最高,其次為最近的namespace下的靜態類的靜態方法,最後為較遠的namespace下的靜態類的靜態方法。

4、是一種編譯技術,注意與反射等執行時技術進行區別,並慎重使用。

-------------------------------------------------------------華麗分割線---------------------------------------------------------------------

1、LINQ
提供一種跨越各種資料來源的統一的查詢方式,包含Linq to Objects、Linq to XML、Linq to DataSet、Linq to SQL;

查詢表示式必須以from開頭,以select或group結尾,中間可以包含一個或多個where、orderby、join等子句;

2、dynamic定義動態型別,編譯器不知道它的型別,只能在程式執行時才能確定;

4、反射:

5、正則表示式: