[C#]C#學習筆記-索引器,指標類型,隱式類型,擴充方法,分部方法,匿名型別

來源:互聯網
上載者:User

C#學習筆記-索引器,指標類型,隱式類型,擴充方法,分部方法,匿名型別

羅朝輝(http://www.cnblogs.com/kesalin/)

《C#與.NET進階程式設計》讀書筆記

索引器,指標類型 

1,可以使用索引器方法 this[Type param] 來自訂一個類型的索引器。C#編譯器為索引器方法建立了一個名為 Item 的屬性來映射正確的擷取/設定方法。舉例:

public Person this[int index]
{
get { return (Person)list[index];
set { list.Insert(index, value);
}

2,索引器方法可以被重載,也可以可以實現多維的索引器,也可以在介面中定義索引器。

3,運算子多載:[], (), 以及簡寫賦值運算子(+=,-=等)不可重載,而 true, flase 也可以用作運算子。C#中如果一個類型重載了相關的二元運算子,與之對應的簡寫賦值運算子會自動具有相應的新功能。同樣,我們也需要重載前增++或前減--就能自動獲得後增或後減的功能。在C#中重載==運算子時必須同時重載!=運算子(如果不這麼做,編譯器會提示的),這規則適用於所以基於比較的運算子(>, <, >=, <=)。重載運算子在內部是通過隱藏方法來表示的。比如:op_Addition(), op_Equality()等。我們也可以在其他不支援重載運算子的語言中調用這些靜態隱藏方法。

4,C#還支援自訂轉換,轉換方法必須定義為靜態。如將Rectangle 轉換為 Square。與重載運算子一樣,包含 implicit 或 explicit 關鍵字的方法在 CIL 中分別對應專門的指令 op_Implicit 和 op_Explicit。

public static explicit operator Square(Rectangle r)
{
Square s;
s.Length = r.Height;
return s;
}

5,C#也支援原始的指標類型,以及相關的指標操作,我們應該明確設定編譯器的 /unsafe 設定,以表示支援不安全編碼。我們使用 unsafe 關鍵字來特別聲明一個代碼區塊(包括結構,類,類型成員或參數)為不安全的程式碼。如下關鍵字用於不安全編碼:stackalloc(直接從調用棧分配記憶體),fixed(用於將不安全上下文記憶體中的參考型別變數地址固定,這樣在執行過程中記憶體回收行程就不會重設該變數的地址)以及 sizeof。

6,預先處理指令:在C#中沒有獨立的預先處理步驟,而是在編譯器的詞法分析階段處理預先處理指令。除了傳統的#define, #if系列,C#還增加了用於標記代碼區塊的 #region, #endregion預先處理指令。

隱式類型

7,var 關鍵字(準確地說 var 不是關鍵字,我們可以聲明名為 var 的變數,參數或欄位而編譯器不會報錯):我們可以使用 var 替代正式的資料類型名來局部變數,參數和欄位,編譯器會根據用於初始化局部變數的初始值推斷變數的資料類型。隱式類型局部變數是強型別資料。如:

static void DeclareImplicitVars()
{
var myInt = 0;
var myBool = true;
var myString = "It's a string";
}

使用 var 定義隱式類型局部數組時,數組初始化式中的各數群組成員必須為同一可推斷的類型。隱式類型局部變數不會預設設定為 System.Object。

var d = new[] {1, 10, 100, 100};

8,使用 var 有一些限制:首先,顯式類型只能應用於方法或者屬性內局部變數的聲明,不能使用 var 來定義傳回值,參數的類型或者類型的資料成員。其次 var 進行聲明的局部變數必須在聲明時同時賦值,並且不能以null作為初始值。再次,不能使用C#的?標識來定義可空隱式類型局部變數。

9,隱式類型局部變數的作用:LINQ技術使用查詢運算式,它可以動態根據查詢本身的格式來建立結果集,這樣我們可以使用 var,從而不需要顯式定義查詢可能會返回的類型。

自動屬性

10,自動屬性:為了簡化簡單欄位資料封裝的過程,C#3.0開始提供自動屬性文法,這個特效能讓我們使用新的文法為編譯器定義支援欄位和相關的C#屬性。如果我們想要定義抽象屬性的話,還需要使用 abstract 關鍵字。注意:如果要定義自動屬性,就必須提供讀和寫兩個功能,我們不能構建唯讀或唯寫的自動屬性。樣本:

class Car 
{
public sting Name { get; protected set; };
}

擴充方法

11,C#3.0中,我們可以把方法定義為擴充方法。簡單地說,擴充方法允許現存已編譯的類型(如類,結構,介面)和當前即將被編譯的類型(如包含擴充方法的類型)在不需要被直接更新的情況下,獲得功能上的擴充。這樣通過擴充方法,我們可以為先行編譯的類型(甚至我們並不擁有該類型的代碼)添加功能,同時這些方法將獨立分開存放。

12,使用擴充方法有一些限制:第一,擴充方法必須是靜態;第二,所有的擴充方法都需要使用關鍵字 this 對第一個參數(並且僅對第一個參數)進行修飾;第三,每一個擴充方法只可以被記憶體中正確的執行個體調用,或者通過其所處的靜態類被調用。樣本:該擴充允許所以System.Int32將自己的值倒置。

static class MyExtensions
{
public static int ReverseDigits(this int i)
{
char[] digits = i.ToString().ToCharArray();
Array.Reverse(digits);
string newDigits = new string(digits);
return int.Parse(newDigits);
}

13,在使用擴充方法的背後編譯器僅僅以普通的方式調用靜態方法,即把調用方法的變數作為調用參數(就是 this)。如上面的例子,編譯器會在背後轉換為 MyExtensions.ReverseDigits(aInt),因此我們可以使用普通C#文法像調用普通靜態方法那樣調用擴充方法。

14,由於擴充方法的靜態性,我們不能在擴充方法中直接存取它擴充的類型的成員,但我們可以使用 this 來方法要擴充類型的所以公用成員(僅僅是公用成員)。

15,擴充方法的範圍:把包含擴充方法的靜態類型放到獨立的命名空間中後,處於同一程式集的其他命名空間可以使用標準的C#關鍵字 using 匯入這些靜態類型和它們包含的擴充方法。需要牢記的是,如果沒有顯示地匯入正確的命名空間,擴充方法對當前C#代碼檔案是停用。

16,微軟推薦把擴充方法放在獨立的程式集(獨立的命名空間)-擴充庫,從而方便代碼的模組化與管理。我們不僅可以擴充類還可以擴充介面。擴充介面稍微有點特別,我們擴充一個介面使其具有新成員的時候,必須提供這些成員的實現,這似乎已經脫離介面類型的本質(實際上是實現該介面的所以類型都具有靜態新成員實現)。

分部方法(partial)

17,我們可以使用 partial 關鍵字來構建部分類別定義,這樣我們可以跨多個代碼檔案實作類別型的文法,只有每一個部分型別具有同樣的完全限定名。在C#3.0起,我們可以把 partial 應用到方法層級,它允許我們在一個檔案中構建方法原型,而在另一個檔案中實現,但這樣做有許多限制。第一,分部方法只可以定義在部分類別中;第二,分部方法必須返回 void;第三,分部方法可以是靜態或執行個體層級的;第四,分部方法可以有參數(包括被 this,ref或params修飾的參數,但不能具有 out 修飾符);第五,分部方法總是隱式私人的;第六,分部方法可能會放在已編譯的程式集中,也可能不會,因為編譯器會根據方法體是否實現來決定方法是否應該放到程式集中來,如果沒有方法體的話,所以方法的使用痕迹(調用,中繼資料描述以及原型)都會在編譯時間去除。

18,由於分部方法必須是隱式私人的並總是返回 void,所以分部方法的用途並不大。通過用 partial 修飾符標記文法,其他類的構建者可以選擇提供實現細節,這樣,分部方法就提供了比使用預先處理指令更簡潔的方案,為虛方法提供了虛擬實現或拋出NotImplementException異常。此外使用分部方法來定義輕量級事件是很常見的,這使得類設計者可以提供方法掛鈎,就像事件處理常式一樣,開發人員可以選擇實現或不實現來決定是否需要響應某事件。根據命名規範,這樣的輕量級事件處理方法使用On首碼。

初始化

19,對象初始化器是以從左至右方式進行的。對於容器,我們可以使用集合初始化文法,此文法使我們可以像初始化普通數組一樣初始化容器。

匿名型別

20,匿名型別是匿名方法的自然延伸。當定義一個匿名型別,需要使用新的關鍵字 var 和前面介紹的對象初始化文法。比如:

static void Main(string[] args)
{
// 構建一個匿名對象表示一輛汽車
var myCar = new { Color = "White", Make = "Saab", CurrentSpeed = 60 };
Console.WriteLine(" >> My car is a {0} {1}.", myCar.Color, myCar.Make);
}

21,所有的匿名型別都自動繼承 System.Object,因此它們都支援基類的每一個成員,因此我們可以在其上調用 GetType(), ToString()等方法。匿名類的類型名完全由編譯器決定的,使用對象初始化文法定義的每一個成對的名稱和數值分別被映射為擁有相同名字的屬性以及對應被該屬性封裝的私人資料成員。判斷匿名型別的對象相等(Equals())是基於值的語義,即比較兩個對象的每一個資料成員的值,但匿名型別並沒有重載C#的相等運算子(=和!=),因此相等運算子還是基於比較引用的。

22,匿名型別的用途:應該謹慎地使用匿名型別,尤其是使用 LINQ 技術時(快速構建一個實體而不需要定義其功能)。匿名型別有很多限制:第一,你不能控制匿名型別的名稱;第二,匿名型別繼承自 System.Object;第三,匿名型別不支援事件,自訂方法,自訂運算子和自訂重寫;第四,匿名型別是隱式封閉的(sealed);第五,匿名型別的執行個體建立只使用預設建構函式。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.