C#學習筆記第三發---進階特性

來源:互聯網
上載者:User

標籤:按鈕   操作   資料查詢   執行   linq查詢   檔案夾   通知   erro   子目錄   

一、異常處理機制

編寫的程式在編譯不報錯之後並不是就不會出錯了,在運行時由於邏輯問題或者別的原因還是可能出現各種異常,異常處理機制就是為了處理這種情況。異常處理中需要用到三個關鍵字,try、catch、finally。其中try下的大括弧內寫可能出現異常的代碼塊,catch下的大括弧寫異常的處理方式(catch需要有輸入參數,參數就是異常類,在不確定異常種類時可以用Exception類,因為這是所有異常類的父類),finally下大括弧寫可能異常的代碼塊運行結束後的代碼,比如釋放空間等,寫在finally外則在出現異常時不會運行,必須寫在finally內。還有一個關鍵字是throw,用於拋出異常。一個try可以有多個catch,會根據異常類型的設定跳入到相應的catch內,類似於重載。異常處理戶佔用大量的系統資源,要盡量減少。

二、I/O操作

 I/O操作是指檔案讀寫或者是硬碟上的讀寫,相關的有檔案的讀寫,路徑的操作和檔案夾的操作。常用的類有File和Directory兩個靜態類,File用於檢查檔案(夾)是否存在、複製、 移動、 重新命名、 建立、 開啟、 刪除和一次開啟單一檔案等操作,Directory用於通過目錄和子目錄進行建立、移動和枚舉等操作。如果要建立實體類,則要用到FileInfo和DirectoryInfo這兩個實體類,FileInfo類提供建立、複製、刪除、移動和開啟檔案的執行個體方法,並且可以協助建立FileSteam對象,DirectoryInfo類用於建立、移動和枚舉目錄和子目錄的執行個體方法。寫檔案時有兩種方式,一種是先建立FileStream類,定義檔案的檔案名稱和操作,使用BinaryWriter類執行個體化一個方法,來進行寫入,具體代碼如下:

FileStream fs=new FileSteam(FileName,FileMode.Create);

BinaryWrite w=new BinaryWrite(fs);

w.Write("a");

w.close();

fs.close();

另一個方法就是使用StreamWrite方法建立實體類,使用類下的方法Write和WriteLine寫入,具體實現如下:

StreamWrite w=File.AppendText("FileName.txt");

w.WriteLine("Hello");

w.Flush();

讀操作類似於寫操作,只是使用的類是FileReader,使用的方法是ReadLine,具體實作類別似於寫操作。

三、索引器

 Indexer索引器可以讓class想數組一樣訪問每個元素,相當於重寫了一個實體類的this方法,所以索引器必須使用this命名。索引器包括get和set方法,實現如下:

public string this[int index]

{

get

{

string tmp;

if(index>=0&&index<=nameList.Length-1)

{

tmp=nameList[index];

}

else{

tmp="";

}

return tmp;

}

set

{

if(index>=0&&index<=nameList.Length-1)

{

nameList[index]=value;

}

}

}

在main函數中,調用建立實力類數組的方法後,就可以預設的使用索引器進行讀寫操作。索引器中不強制規定索引類型和傳回值類型,不同的索引器可以通過改變索引類型的方法重載,類似於方法的重載,輸入參數數目的改變也可以重載(用於多維陣列)。

索引器還可以應用於介面,在介面中索引器的get和set不需要寫具體實現,在繼承他的class中再實現具體方法

四、委託

委託相當於一個函數指標,需要在main函數外聲明,聲明格式為:delegate 傳回值類型 委託名(參數類型 參數名)。然後再main函數中對委託執行個體化,直接使用委託名new一個新的執行個體化對象,在new時要代入符合委託定義時的參數類型的方法(方法寫在main外,可以使用靜態方法或者執行個體化的方法),然後使用執行個體化的委託實現方法。使用靜態方法時,執行個體化委託時可以直接調用方法,使用執行個體化方法內的委託時,要先建立執行個體化對象的執行個體,然後調用委託,調用時參數寫:執行個體名.方法。同一個委託可以調用多個方法。使用委託可以實現多重委託(Multi-casting delegatte),使用+或者-將多個委託串連後賦值一個新的委託,新的委託會按照添加順序順序執行每個委託,-的時候不必嚴格按照添加順序,會根據添加順序取消最後一個添加的該委託,-一個不存在於列表的委託不會造成任何影響。

五、事件

 常用語圖形化互動介面中,用於通知程式發生了一些事件(比如滑鼠點擊,鍵盤輸入等),便與程式下一步執行。事件編寫在Windows Forms Application而不是Console Application。使用工具箱內的工具可以方便的添加各種功能,雙擊就可以編寫依存於添加按鈕或者框體的事件。使用控制台編寫時事件和委託要一起命名,先定義委託,定義事件時,要在事件名之前加入委託名,表示該事件可以觸發這個委託。使用event關鍵字命名事件,在main函數中通過+=將具體的委託綁定到事件上。event可以被繼承,也可以在interface的實作類別裡實現。事件內要寫實作類別,來判斷事件是否綁定了委託,非空則執行。與事件綁定的委託推薦的寫法是:

public delegate void 委託名(object sender,EventArge e),其中object類表明出發的條件,EventArge表示與事件相關的一些參數,C#自身有一個方法EventHandler,可以在定義事件時,使用這個方法來正常化定義的事件

六、泛型

泛型在對不同資料類型的資料進行相同的操作時可以省去重複代碼。在定義一個class時,在class名後加<T>,表示使用泛型,在class內部可以使用T表示不確定的資料類型,執行個體化時在<>內填入資料類型,就建立了使用對應資料類型的對象,可以使用class內的方法操作執行個體化對象。定義泛型時,可以規定多重泛型<T,K>,在<>後可以約束泛型的範圍使用語句where T:struct 就規定T只能使用不可為空的類型。使用泛型的類在被繼承時可以規定一個類,子類就不再實現泛型,如果子類也要實現泛型,則在子類名後需要加<T>,就可以繼續使用泛型。在方法上使用泛型時,在方法名後添加<T>,就可以在本方法內實現泛型的使用,調用方法時再規定具體的類型。 在方法中引用數值時,在資料類型前加ref表示調用參考型別,即在方法中改變值時會改變資料實際的值,不必再傳回值。在委託中也可以使用泛型,定義委託時,傳回值和輸入值都是用T代替,定義類時,只要符合規範就可以作為委託調用,另外,定義介面、事件上實現,定義方式類似。

七、Attribute

 Attribute用來添加附加的聲明資訊,C#內建了一些Attribute。

1、Conditional

在方法前寫[Conditional("DEBUG")],則只有在debug模式下或者在程式前註明#define DEBUG的情況下,才會運行此類中的方法。

2、Obsolete

在方法前寫[Obsolete ("Don‘t use Old Meltod"),ture]表示這是一個過時的方法,調用時會報錯。

3、AttributeUsage

用於自訂的Attribute,其中可以帶幾個參數來規定這個自訂Attribute的適用範圍等。

使用者也可以自訂Attribute,自訂的Attribute繼承於Attribute類,命名時自訂的Attribute名為自訂名加Attribute關鍵字組成,調用時可以使用完全名,也可以不寫Attribute關鍵字,使用縮減的寫法調用,下面是一個自訂Attribute的例子,定義了一個名為HelpAttribute的自訂Attribute,可以被應用於類,不可以在同一個單元重複使,不被繼承:

[AttributeUsage(AttributeTargets.Class,AllowMultiple=flase,Inherited=flase)]

public class HelpAttribute:Attribute

{

protected string description;

public HelpAttribute(string description_in)

{

this.description=description_in;

}

public string Description

{

get

{

return this.description;

}

}

}

在調用這個自訂Attribute時,既可以使用HelpAttribute也可以使用Help,調用語句為[Help("this is a class")]。

在main函數中,可以通過反射或者這個類的Attribute攜帶的資訊,擷取方式如下:

HelpAttribute helpAttribute;

foreach(var attr in typeof(AnyClass).GetCustomAttribute(ture))

{

Console.WriteLine("AnyClass Description:{0}",helpAttribute.Description);

}

Console.ReadLine();

就能輸出自訂的Attribute攜帶的資訊。

八、反射機制

反射就是得到並解析這個類所攜帶的一些資訊,便於程式自行觀測並修改自己結構的行為。比如使用Type類建立實體可以獲得一個變數的類型,Type是一個系統內建的抽象類別,不能直接執行個體化,執行個體化時需要調用其他類的方法。使用反射獲得方法名或其他資訊時,可以在輸入屬性中加入BindingFlags標誌位縮小尋找範圍。

九、預先處理指令

預先處理指令可以讓C#編譯器在編譯開始前預先處理一些資訊,C#中預先處理指令不能預定義宏函數,也不能給預先處理指令賦值常量。常用的預先處理指令有地區預先處理指令#region、#endregion配對使用,使得兩者之間的內容可以被摺疊起來,只顯示第一行的內容,使得代碼簡潔明了。條件預先處理指令#define、#undef、#if、#else、#elif、#endif,在程式開始處使用#define命名一個條件變數,可以使用#undef是這個變數無效化,在程式中,使用#if和#endif包裹起來的部分就會被判斷,#if條件符合#define規定的變數名就會運行#if後的代碼,不符合則運行#else後的代碼。#elif使用於#if中類似於條件陳述式的elseif。警告預先處理指令#waring,可以用於程式任意位置,會在編譯時間強制拋出警告,#error類似於#waring用於強制拋出錯誤。行數規定指令#line,之後寫一個整型變數,用於強制改變行數,或者寫一個string變數,強制改變檔案名稱,寫default用於恢複行數顯示。自訂預先處理指令#pragma設定編譯器狀態或者指示編譯器完成一些動作,比如#pragma message(“””)會在控制台輸出裡面的內容可以作為標識、#pragma warning改變錯誤警告的提示。

十、Regex

Regex是對字串操作的一種公式,通常的操作有匹配、過濾、擷取。Regex中會用到很多符號,以下是一個總結:

.所有字元\.匹配.

\d數字

\D非數字

\s空格

\S非空格

\w字元

\W非字元

\b邊界

[]單個字元,裡面的字元或關係

{}重複多次,填入兩個逗號隔開的數字表示兩個次數之間都可以匹配

*零個或者多個

+一個或者以上

?零個或者一個

^以……開始

$以……結尾

()顯示位置

$&原字串

等等。

C#的Regex都在Regex類下,通常使用有兩種方法,一種是使用靜態方法,一種是執行個體化Regex,同一Regex的Regex只能執行個體化一次。

匹配是否有相同內容使用的方法名是Match,需要填入兩個參數作為對比。

替換使用的方法是Replace,共有三個參數,第一個是被修改的參數,第二個是匹配條件,第三個是修改的樣式。

分割字串使用Split,有兩個參數,第一個是被分割的字串,第二個是費根條件,得到的是一個分割後的數組。

十一、匿名函數

匿名函數是指一段函數或者運算式直接嵌套在程式中,沒有專門的函數名。與委託區分就是委託是將一些已經命名的函數或者方法傳遞到程式中,匿名函數是把一個沒有名稱的方法或者函數傳遞到程式中。

使用委託實現一個方法的調入如下:

在main函數外需要寫以下代碼:

delegate void d(string s);

static void M(string s)

{

Console.WriteLine(s);

}

main函數中調用:

d test =new d(M);

在C#2.0版本中,提供了匿名函數的方法實現(Anonymous Method),在main函數外定義委託後,只需要在main函數中寫以下代碼:

d test =delegate(string s){Console.WriteLine(s);};

而在C#3.0版本中,更進一步的省略了寫法(Lambda Expression):

d test =(s)=>{Console.WriteLine(s);};

以上方法的實現結果是一樣的。

在沒有參數列表時,Lambda列表不能實現委託的調用,只能使用匿名函數。

使用匿名函數的方法時在new的方法後(delegate(){})delegate中寫參數列表,{ }中寫具體的實現。匿名方法的參數不能使用ref,out等關鍵字修飾,也不能使用is關鍵字判斷類型,匿名方法不能使用於不安全模式。

lambda運算式由三個部分組成,()=>{}左邊是參數列表,中間是=>符號,右邊是具體的實現。只有一個參數時,可以不寫()

十二、LINQ

Linq:Lanuage Intergarted QueryLanguage-integrated Query (LINQ),是對資料查詢或者操作的語句,彌補了物件導向的編程和資料庫的間隙,沒有Linq語句時,是無法對sql等類型的語句中的查詢目標進行類型檢查的,而使用Linq查詢語句可以對不同的資料類型進行相似的處理,Linq語句對實現了IEnumerable介面的資料都能使用Linq語句查詢。常用的Linq查詢有Linq to sql、Linq to XML、Linq to DataSet、Linq to Objects。

Linq的實現方式有以下兩種:

1、Query syntax

查詢偶數的文法如下

var numQ=from num in numbers

                  where num%2 == 0

                  orderby num

                  select num;

就實現了查詢numbers數組中的偶數並排序,調用結果時,使用foreach(var i in numQ)就可以調用查詢結果。

Query語句一般使用三步走的方式實現,第一步建立資料來源,就是建立要查詢的來源資料;第二步建立Query語句查詢;第三步使用迴圈調用查詢結果。

查詢中常用的關鍵字有from(擷取資料來源)、in(來源資料數組)、where(過濾條件)、orderby || group by(排序)、select(結果輸出)、join(串連查詢),使用迴圈調用結果時,調用查詢語句名。再用到這個語句時,他才會被執行,如果要強制執行,可以調用查詢結果下的方法。

where過濾條件中可以使用&&和||進行與或邏輯設定。

orderby排序預設為升序,可以使用descending降序排列,ascending表示升序。

group可以根據索引值排序:from c in customers group c by c.city就是對c根據其城市屬性排序。

join串連查詢類似於sql的串連查詢方式:from c in customers join e in emp on c.name equals e.name select new {name=c.name,id=e.id,city=c.city}就能查詢到兩個列表中具有相同name的資料,並按照new的定義輸出資訊。

into用於group排序後的資料,相當於對group查詢到的資料進行打包,可以在where中使用打包的資料名進行一些其他的操作。

let相當於一個中間變數,對資料進行一步處理,產生一個新的變數名,後面的步驟就可以操作這個變數名。

舉例let:

from s in strings 

let w=s.ToUpper()

select w;

就將strings中的資料變成了大寫。

2、Method syntax

var numQ=numbers.where(n=>n%2==0).OrderBy(n=>n);

調用方法實現查詢,結果相同。

十三、擴充方法

ExtensionMethod擴充方法可以在不修改類的基礎上,給類提供一些方法,例如Linq語句就可以為數組提供排序的方法,但是這個排序方法並不在數組的類型下。

自訂擴充方法必須是一個靜態類下的靜態方法,定義方法是:

public static class 類名

{

public static 傳回值類型 方法名(this 被擴充的類名 參數名)

{

具體方法;

}

}

類名並不重要,不會影響實現,調用時,使用被擴充的類名的執行個體化對象調用方法名就可以實現調用。注意必須在方法名中使用this關鍵字標明被擴充的方法名,如果需要其他參數,可以在方法名的參數列表中this標出的變數名後用逗號隔開標明。

十四、初始化器

初始化器就是在一個類、對象或者集合初始化時候對其中的屬性或者欄位初始化值,初始化器分為對象的初始化器和集合的初始化器。

1、對象的初始化器

對於類StudentName定義如下:

public class StudentName

{

public string firstname{get;set;}

public string lastname{get;set;}

public int ID{get;set;}

public StudentName()

{

}

public StudentName(string firstname,string lastname)

{

firstname=firstname;

lastname=lastname;

}

}

對於這個類執行個體化時,使用不同的方式:

var StudentName1=new StudentName(“mi”,“wang”);

var StudentName2=new StudentName{firstname=“mi”,lastname=“wang”};

 得到的執行個體化對象屬性是一樣的,而StudentName2使用的就是初始化器的方法。初始化器調用的是預設的建構函式,而StudentName1使用的是重載後的建構函式。使用初始化器,可以直接存取到可以被訪問的類內的屬性直接命名,而不用重寫建構函式。使用建構函式和初始化器是可以一起使用的,如下:

var StudentName3=new StudentName(“mi”,“wang”){ID=20};

2、匿名類的初始化器

var pet=new {age=10,name=“mimi”};

就可以直接定義一個對象pet,具有屬性年齡和名字,而不用專門的定義pet類,但是這個對象的屬性是唯讀,不能後續修改。

Linq語句的查詢結果就可以使用匿名類重定義輸出結果的資料結構。

3、集合的初始化器

在定義列表和索引值對時,可以對其中的每個對象使用初始化器的定義方式定義其中的資料。

C#學習筆記第三發---進階特性

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.