標籤:部分 return -o index offline 本質 內容 read second
1.結構:結構除了可以含有屬性和欄位,還可以包方法和構造器,但不能包含黠認(無參數}的構造器。有的時候(比如在執行個體化一個數組的時候)不會調用實值型別的構造器,因為所有數組記憶體都轉為用零來初始化,為了避免因為預設構造器只是偶爾調用而造成不一致,C#完全禁止了使用者顯式定義預設構造器,因為編譯器會將聲明時的執行個體欄位賦值放到類型的構造器中進行。在構造器中必須對 struct中的所有欄位進行初始化,如果沒有做到這一點,就會產生編譯錯誤,可查看Angle結構的代碼。
2.結構的繼承與介面:所有實值型別都是密封的,除此之外,所有實值型別都派生自system.ValueType,這意味著struct的繼承鏈息是從object到ValueType到struct。實值型別還能實現介面,許多介面都是實現介面架構固定組成部分,比如 IComparilble 和IFormattable。
3.裝箱與拆箱:裝箱就是把實值型別變成參考型別,如下:
(1) 首先在堆中分配好記憶體,它將用於存放實值型別的資料以及少許額外開銷;
(2) 接著發生一次記憶體複製動作,棧上的實值型別資料複製到堆上分配好的位置;
(3) 最後,對象或介面引用得到更新,指向堆上的位置;
拆箱就是把參考型別變成實值型別,如下:根據定義,CIL 指令 unbox 只是對堆上的資料進行解引用,並不包括從堆複製到棧的動作。但在 C#語言中,太多數時候緊接著在拆箱之後發生一次複製動作。裝箱和拆箱之所以重要,是因為裝箱去對效能和行為造成一些影響。開發人員可以通過查看CIL,在一個特定的程式碼片段中統計 box/unbox 指令的數量。在BoxAndUnbox()中的代碼就存在多次的裝箱與拆箱,這樣編寫的代碼是不合理。
4.枚舉:枚舉和其他實值型別稍有不同,因為枚舉的繼承鏈是從System.ValueType到System.Enum,再到enum。
5.枚舉與字串的轉換:枚舉ToString()後會輸出枚舉標識符,使用Enum.Parse或Enum.TryParse方法可以把字串轉化為枚舉,後一個方法是.Net4.0新增的泛型方法。此中我們也可以使用Enum.IsDefined()方法來檢查一個值是否包含在一個枚舉中。
6.枚舉作為“位標誌”使用:
(1)可以查看如下“FileAttributes“枚舉的設定(即System.IO。FileAttributes的設定),作為位標誌後,其值可以自由組合,所以可以使用Or運算子來連接枚舉值。如本樣本中BitFlag()方法的使用。當然枚舉中的每個值不一定只對應一個標誌,完全可以為常用的標誌組合定義額外的枚舉值。
(2)使用位標誌類型的時候,位標誌枚舉應該包含[FlagsAttribute]這個特性,這個標誌指出多個枚舉值可以組合使用,此外,它改變了ToString()和Parse()方法的行為。例如為一個已用FlagsAttribute修飾了的枚舉調用ToString()方法,會為已設定的每個枚舉標誌輸出對應的字串(如BitFlag2()的樣本),而如果沒有這個修飾,返回的就是組合後數值。
public struct Angle{ public Angle(int hours, int minutes, int seconds) { Hours = hours; Minutes = minutes; Seconds = seconds; } public int Hours { get; set; } public int Minutes { get; set; } public int Seconds { get; set; } public Angle Move(int hours, int minutes, int seconds) { return new Angle(Hours + hours, Minutes + minutes, Seconds + seconds); }}[Flags]public enum FileAttributes{ ReadOnly = 1 << 0, Hidden = 1 << 1, System = 1 << 2, Directory = 1 << 3, Archive = 1 << 5, Device = 1 << 6, Normal = 1 << 7, Temporary = 1 << 8, SparseFile = 1 << 9, ReparsePoint = 1 << 10, Compressed = 1 << 11, Offline = 1 << 12, NotContentIndexed = 1 << 13, Encrypted = 1 << 14}public void BitFlag(){ string fileName = @"enumtest.txt"; FileInfo file = new FileInfo(fileName); file.Attributes = FileAttributes.Hidden | FileAttributes.ReadOnly; Console.WriteLine("{0} | {1} = {2}", FileAttributes.Hidden, FileAttributes.ReadOnly, (int)file.Attributes); if ((file.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden) { throw new Exception("File is not hidden"); } if ((file.Attributes & FileAttributes.ReadOnly) != FileAttributes.ReadOnly) { throw new Exception("File is not read-only"); } //....}public void BitFlag2(){ string fileName = @"enumtest.txt"; FileInfo file = new FileInfo(fileName); file.Open(FileMode.Create).Close(); FileAttributes startingAttributes = file.Attributes; file.Attributes = FileAttributes.Hidden | FileAttributes.ReadOnly; Console.WriteLine("\"{0}\" output as \"{1}\"", file.Attributes.ToString().Replace(",", "|"), file.Attributes); FileAttributes attributes; Enum.TryParse(file.Attributes.ToString(), out attributes); Console.WriteLine(attributes); File.SetAttributes(fileName, startingAttributes); file.Delete();}public void BoxAndUnbox(){ int totalCount; ArrayList list = new ArrayList(); Console.Write("Enter a number between 2 to 1000:"); totalCount = int.Parse(Console.ReadLine()); list.Add((double)0); list.Add((double)1); for (int i = 2; i < totalCount; i++) { list.Add((double)list[i - 1] + (double)list[i - 2]); } foreach (double num in list) { Console.Write("{0},", num); }}
----------------------以上內容根據《C#本質論 第三版》進行整理
C#學習筆記6