枚舉|標誌枚舉+|(或)和&(與)運算|類型轉換|值類型和引用類型|傳參|異常|垃圾回收

枚舉部分

  enum 關鍵字用於聲明枚舉,即一種由一組稱爲枚舉數列表的命名常量組成的獨特類型。程序員

  一般狀況下,最好是在命名空間內直接定義枚舉,以便該命名空間中的全部類都可以一樣方便地訪問它。 可是,還能夠將枚舉嵌套在類或結構中。默認狀況下,第一個枚舉數的值爲 0,後面每一個枚舉數的值依次遞增 1。數據庫

  例1:編程

  //此枚舉的默認值是從0開始數組

  enum Days {Sat, Sun, Mon, Tue, Wed, Thu, Fri};安全

  例2:網絡

  //此枚舉的默認值是從1開始,下標爲3的tue值爲7,從下標3開始的值依次加1。數據結構

  enum Days {Sat=1, Sun, Mon, Tue=7, Wed, Thu, Fri};ide

  每種枚舉類型都有基礎類型,該類型能夠是除 char 之外的任何整型。 枚舉元素的默認基礎類型爲 int。 要聲明另外一整型枚舉(如 byte),請在標識符以後緊跟類型,而後再使用冒號,如例3所示。准許使用的枚舉類型有 byte、sbyte、short、ushort、int、uint、long 或 ulong。enum E 的默認值爲表達式 (E)0 生成的值。函數

  //例3:性能

  //此枚舉的類型是byte,值從0到255

  enum Days : byte {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};

  枚舉數的名稱中不能包含空白。

  基礎類型指定爲每一個枚舉數分配的存儲大小。 可是,從 enum 類型到整型的轉換須要用顯式類型轉換來完成。 例如的語句使用強制轉換(從 enum 轉換爲 int)將枚舉數 Sun 賦值給一個 int 類型的變量,例4所示。

  例4:

  int x = (int)Days.Sun;

  能夠將任意值賦給枚舉類型的枚舉數列表中的元素,也可使用計算值,如例5。

  例5:

  enum MachineState{ PowerOff = 0, Running = 5, Sleeping = 10, Hibernating = Sleeping + 5}

  與任何常量同樣,對枚舉中各個值的全部引用在編譯時均將轉換爲數值文本。

  注意:默認輸出的是文本值,轉換後變爲數字。只要給枚舉賦予的值在枚舉變量容納枚舉定義的值以內,就能夠給枚舉賦予數字(建議不要這樣作)。

  標誌性枚舉

  建立位標誌枚舉的方法是應用 System.FlagsAttribute 特性並適當定義一些值,以即可以對這些值執行 AND、OR、NOT 和 XOR 按位運算。 在位標誌枚舉中包含一個值爲零(表示「未設置任何標誌」)的命名常量。若是零值不表示「未設置任何標誌」,則請不要爲標誌指定零值。

  [Flags]

  enum Days2{ None = 0x0, Sunday = 0x1, Monday = 0x2, Tuesday = 0x4, Wednesday = 0x8,    Thursday = 0x10, Friday = 0x20, Saturday = 0x40}

  class MyClass{  Days2 meetingDays = Days2.Tuesday | Days2.Thursday;}

  爲枚舉建立新方法

  可使用擴展方法添加特定於某個特定枚舉類型的功能。

  請參見:http://msdn.microsoft.com/zh-cn/library/bb383974.aspx

  枚舉小結

  獲取當前枚舉的基礎值類型:Enum.GetLinderlyingType(typeof(MyColor));

  枚舉轉換:

  將枚舉轉換爲數值:(int)Mycolor.Red

  將枚舉轉換爲字符串:MyColor.Red.ToString()

  將字符串轉換爲枚舉:MyColor mc=(MyColor)Enum.Parse(typeof(Type),"value")

 標誌枚舉

  枚舉加上【Flags】就成爲標誌枚舉,加上這個特性後枚舉類型.ToString()返回的就是文字形式,不是數字。

  代碼以下:

  FileAttributes classfileAttributes= FileAttributes.Hidden|FileAttributes.ReadOnly;

  Console.WriteLine(classfileAttributes.ToString());//結果是ReadOnly,Hidden;

  轉到源碼查看:

  咱們修改枚舉類,仍是圖片上的代碼,只是去掉全部標記。還用上面的代碼,你會發現輸出的值是一個數字而不是字符串。

首先咱們要知道,普通枚舉中的每一個值都是互斥的(輸出結果只能是一個),而標誌枚舉中的每一個值是能夠互相組合的,輸出結果能夠是多個,多個時值之間用逗號隔開,且計算後的結果是字符而不是數字。(這裏說的計算是與或計算,&、|)。固然標誌枚舉用的string類型(顯示的),而計算時用的是賦的值。

  該給枚舉賦什麼樣的值呢?

  標誌枚舉規賦值儘可能用2的次方進行標記賦值。查看微軟的代碼會發現:微軟用2的次方給枚舉賦值。

標誌枚舉有什麼特色呢?

  1. 單個枚舉組合成集合,能夠同時輸出多個值。用|運算能夠枚舉值組合在一塊兒,以下。

  FileAttributes.ReadOnly| FileAttributes.Hidden進行計算時,把它進行轉換:

  FileAttributes.ReadOnly :00 00 00 01  →1

  FileAttributes.Hidden   : 00 00 00 10  →2

  |運算——————————————————————————

                                           00 00 00 11   → classfileAttributes的集合

  這ClassFileAttribute就是咱們取值的集合,而後再通過轉換輸出輸出,輸出這個組合的值。

 

  2.判斷枚舉集合中是否包含某個枚舉值。例如:判斷FileAttributes.ReadOnly是否在classfileAttributes集合中。

使用代碼:If( (classfileAttributes&FileAttributes.ReadOnly)== FileAttributes.ReadOnly)//代碼

  計算過程:

  classfileAttributes       :    00 00 00 11

  FileAttributes.ReadOnly  :00 00 00 10

  &運算————————————————————

                                            00 00 00 10  →      FileAttributes.ReadOnly

  若是FileAttributes.ReadOnly在classfileAttributes集合中,則計算結果爲這個值。接着用這個值進比較。

類型轉換部分

  每一個值都有與之關聯的類型,此類型定義分配給該值的空間大小、它能夠具備的可能值的範圍以及它能夠提供的成員等特性。許多值能夠表示爲多種類型。 例如,值 4 能夠表示爲整數或浮點值。類型轉換能夠建立一個等同於舊類型值的新類型值,但卻沒必要保留原始對象的恆等值(或精確值)。

  .NET Framework 提供了多個功能來支持類型轉換。包括:

  Implicit 運算符,該運算符定義類型之間可用的擴大轉換(隱式轉換)。

  Explicit 運算符,該運算符定義類型之間可用的收縮轉換(顯示轉換)。

  IConvertible 接口,該接口定義到 .NET Framework 每一個基數據類型的轉換。

  Convert ,該類提供了一組方法來實現 IConvertible 接口中的方法。

  TypeConverter ,該類是一個基類,能夠擴展該類以支持指定的類型到任何其餘類型的轉換。具體:參見此處

  上面是.Net Framework中的類型轉換,下面直說點C#的。

  因爲 C# 是在編譯時靜態類型化的,所以變量在聲明後就沒法再次聲明,或者沒法用於存儲其餘類型的值,除非該類型能夠轉換爲變量的類型。 例如,不存在從整數到任意字符串的轉換。 所以,將 i 聲明爲整數後,就沒法將字符串「Hello」賦予它。

  類型轉換分

  隱式轉換:因爲該轉換是一種安全類型的轉換,不會致使數據丟失,所以不須要任何特殊的語法。例如,從較小整數類型較大整數類型的轉換以及從派生類到基類的轉換都是這樣的轉換。

  顯式轉換(強制轉換):顯式轉換須要強制轉換運算符。在轉換中可能丟失信息時或在出於其餘緣由轉換可能不成功時,必須進行強制轉換。典型的例子包括從數值到精度較低或範圍較小的類型的轉換從基類實例到派生類的轉換

  用戶定義的轉換:能夠定義一些特殊的方法來執行用戶定義的轉換,從而使不具備基類–派生類關係的自定義類型之間能夠顯式和隱式轉換。

  使用幫助程序類的轉換:若要在不兼容的類型之間進行轉換,例如在整數與 System.DateTime 對象之間轉換,或者在十六進制字符串與字節數組之間轉換,則可使用 System.BitConverter 類、System.Convert 類和內置數值類型的 Parse 方法,例如 Int32.Parse。

  使用as和is運算符

  因爲對象是多態的,所以基類類型的變量能夠保存派生類型。 若要訪問派生類型的方法,須要將值強制轉換回該派生類型。 不過,在這些狀況下,若是隻嘗試進行簡單的強制轉換,會致使引起 InvalidCastException 的風險。 這就是 C# 提供 is 和 as 運算符的緣由。 您可使用這兩個運算符來測試強制轉換是否會成功,而沒有引起異常的風險。 一般,as 運算符更高效一些,由於若是能夠成功進行強制轉換,它會實際返回強制轉換值。 而 is 運算符只返回一個布爾值。 所以,若是隻想肯定對象的類型,而無需對它進行實際強制轉換,則可使用 is 運算符。

  Convert

  簡單的說就是將一個基本數據類型轉換爲另外一個基本數據類型。

  Convert 類提供了一種與語言無關的方式來執行基類型之間的轉換,而且該類可用於面向公共語言運行時的全部語言。 它爲擴大轉換和收縮轉換提供了一組完整的方法,而且會對不支持的轉換(例如 DateTime 值到整數值的轉換)引起 InvalidCastException。 收縮轉換是在已檢查的上下文中執行的,若是轉換失敗,將引起 OverflowException。

  除了支持到每一個基類型的轉換外,Convert 類還可用於將一個自定義類型轉換爲一個或多個預約義類型。此轉換是經過 Convert.ChangeType(Object, Type, IFormatProvider) 方法執行的,而此方法包裝了對 value 參數的 IConvertible.ToType 方法的調用。 這意味着 value 參數所表示的對象必須提供 IConvertible 接口的實現。請參見此處

轉換運算符

  C# 容許程序員在類或結構上聲明轉換,以便類或結構與其餘類或結構或者基本類型進行相互轉換。 轉換的定義方法相似於運算符,並根據它們所轉換到的類型命名。 要轉換的參數類型或轉換結果的類型必須是(不能二者同時都是)包含類型。

轉換運算符具備如下特色:

  • 聲明爲 implicit 的轉換在須要時自動進行。
  • 聲明爲 explicit 的轉換須要調用強制轉換。
  • 全部轉換都必須聲明爲 static

  如何使用請參見此處

經驗小結:

  只有在內存存儲上存在交集的類型之間才能進行隱式轉換。

  顯示轉換儘可能使用as。

  將任意類型轉換成字符串:ToString(),(object繼承下來的,通常都有,固然也能夠重寫)。

  將字符串轉換成「數值類型」(int、float、double),可以使用Type.Parse(Type type)、int.TryParse(string str,out int n)【常用】。

  Convert考慮數據意義的轉換。Convert轉換是從新加工、改造的過程,也就是重新組織數據結構。Convert能夠把object類型轉換爲其餘類型。Convert能夠把任意類型轉換爲任意類型。

自娛自樂

  Type.TryParse(Type type)有什麼優勢呢?

  答:Parse()轉換失敗會拋異常,TryParse()轉換失敗不報異常。例如:int  result;bool p=int.TryPase(result,out result) 轉換失敗的話是0。

  爲何說as比is轉換比較高效呢?

  例如:if(p is Student){Student stu=(Student)p;},CLR會進行兩次類型檢查if(檢查一次){//再檢查一次},而as是直接轉換,若是轉換失敗返回null而不會報異常。Is也能夠用GetType()得到類型,而後轉換。GetType()不容許重寫。

值類型和引用類型部分

值類型

若是數據類型在它本身的內存分配中存儲數據,則該數據類型就是「值類型」。 值類型包括:

  • 全部數字數據類型
  • Boolean 、Char 和 Date
  • 全部結構,即便其成員是引用類型
  • 枚舉,由於其基礎類型老是 SByte、Short、Integer、Long、Byte、UShort、UInteger 或 ULong

  每一個結構是值類型,即便它包含引用類型成員。

  能夠經過使用保留關鍵字(例如 Decimal)聲明值類型。 也可使用 New 關鍵字初始化值類型。 這對於值類型有一個帶參數的構造函數的狀況尤其有用。

引用類型

  「引用類型」包含指向存儲數據的其餘內存位置的指針。 引用類型包括:

  • String
  • 全部數組,即便其元素是值類型
  • 類類型,如 Form
  • 委託

  類是一種「引用類型」。 所以,諸如 Object 和 String 之類的引用類型都受 .NET Framework 類支持。 注意,每一個數組都是一種引用類型,即便其成員是值類型。

  因爲每種引用類型表示基礎 .NET framework 類,在初始化時,則必須使用 New 運算符關鍵字,如:Dim totals() As Single = New Single(8) {};

非類型的元素

如下編程元素未限定爲類型,由於您沒法將它們中的任何一個指定爲聲明元素的數據類型:

  • 命名空間
  • 模塊
  • 事件
  • 屬性和過程
  • 變量、常數和字段

使用對象數據類型

  能夠將引用類型或值類型指派給 Object 數據類型的變量。 Object 變量老是存儲指向數據的指針,從不存儲數據自己。 然而,若是爲 Object 變量指派值類型,該變量的行爲將如同存儲本身的數據同樣。可參考該地址

性能問題

  數據傳入方法做爲值類型參數,即在堆棧上建立了每一個參數的副本。很明顯,若是相關參數是大型數據類型(例如,包含不少元素的用戶定義結構),或屢次執行方法,均可能影響性能。在這些狀況下,使用 ref 關鍵字向類型傳遞一個引用可能更爲可取。out 關鍵字相似於 ref 關鍵字,但它會告知編譯器該方法必須爲參數賦值,不然將產生編譯錯誤。

例子

  值類型的內容存儲在堆棧上分配的內存中。例如 int x=42,值 42 存儲在稱爲「棧」的內存區域中。

  定義變量的方法在結束執行或使變量 x 超出使用範圍時,其值則從棧中丟棄。使用棧效率較高,但值類型的生命週期有限,不適合在不一樣類之間共享數據。

  引用類型(例如,類或數組的實例)在另外一個稱爲「堆」的內存區域中分配。

  例如int[] numbers = new int[10],構成數組的 10 個整數所需的空間是在堆上分配的。在方法完成時,並不將此內存歸還給堆;僅當 C# 的垃圾回收系統肯定再也不須要該內存時,才進行回收。聲明引用類型須要更多系統開銷,但它們的優勢是能夠從其餘類進行訪問。

經驗小結

  一個變量是使用基本的內置數據類型之一或用戶定義的結構進行聲明的,則該變量爲值類型。但 string 數據類型除外,它是引用類型。

  全部引用類型都繼承Object。全部的值類型都繼承自System.ValueType[System.ValueType]又繼承自Object。

  值類型和引用類型都用到了棧,值類型的數據存儲在棧上。引用類型的引用地址是存在棧上的,數據是存在堆中。

  引用類型的變量賦值只複製對象的引用。值類型變量賦值會拷貝一個副本。

  Out和Ref

  ref 僅僅是一個地址,引用傳遞,把值傳遞強制改成引用傳遞。

  1.在方法中必須爲out參數賦值,out 讓函數能夠輸出多個值。

  2.out參數的變量在傳遞以前不須要賦值,即便賦值了也不能在方法中使用。

  ref 參數在傳遞以前必須賦值。在方法中能夠不爲ref參數賦值,也能夠直接使用。

  區別是:ref應用場景內部對外部的值進行改變,out則是內部爲外部變量賦值,out通常在函數有多個返回值的場所。當一個方法同時要返回多個值的時候,能夠考慮使用out參數。

  ref主要是把一個值,帶進去再帶出來。out主要是帶出來。

異常部分

  在運行時發生的錯誤才叫異常。語法錯誤,編譯器能夠提示,邏輯錯誤,編譯沒錯,結果不正確,會使程序崩潰。程序崩潰了也要執行finally。

  catch{}//能夠捕獲全部的異常,catcha(Exception ex){} 得到異常的詳細詳細對異常進行分類,

  內部異常直接拋,最外層調用者進行處理。注:throw;只能在 catch中寫。try中有return,finally也照樣執行,但finally中不能寫return語句。

  發生異常後,try塊中,異常代碼後的代碼不會執行。finally塊中的代碼,不管是否發生異常都會執行。

  異常對象:Exception ex。此類封裝了異常發生時的一些信息。

  Exception 類主要屬性:Message、StrackTrace、InnerException

  扔出本身的異經常使用throw,抓住:catch。

  注意:經過邏輯判斷(if-else)減小異常發生的可能性。在多級方法嵌套調用的時候,若是發生了異常,則會終止全部相關方法的調用,而且釋放相關的資源。

傳參部分

  在封裝類時常常封裝方法或構造函數等,封裝時常常須要傳遞參數。而傳參是分值傳遞和引用傳遞。傳參的時候,值傳遞中傳遞的是棧中保存的數據,而引用傳遞則是傳遞自己的地址(棧和堆各有一個地址)。

  值傳遞:傳遞的是棧中的內容,例如:值類型或者引用類型做爲參數傳遞。

  引用類型:需藉助ref和out進行傳遞。

  引用類型的變量(字符了,例如 String str=null中,str就是個變量)是在棧上存儲,堆中開闢地址存放數據。傳參時,引用對象不只傳參的是地址引用,同時也是一個新的對象。例如:在類中的方法傳遞的是類時,此時傳遞進方法體中的參數是一個新的對象。例如:void method(class name){}。name的對象是一個新的對象,只是這個對象指向傳遞進來的對象的地址,也不全是個佔位符。當在這個方法體中從新賦予新的對象時(name=new class(); ),也就從新指向新的地址了(棧上的地址不變,指向堆上的地址發生變化),這時修改這個值時,原來的對象(方法中傳進來的)不會改變。

  小結:我感受有點繞,不過我會繞出來的,寫點方便看懂的。簡單記住就是:值傳遞和引用傳遞均可傳遞引用類型和值類型的值,只是值傳遞是棧中對象的拷貝(拷貝,贗品,可是一個新的),引用傳遞是棧中地址,就是同一對象了。

不過傳遞參數儘可能用接口>抽象類>父類。

補充一點:params能夠爲可變參數直接傳遞一個對應類型的數組。

垃圾回收

  .NET Framework 的垃圾回收器管理應用程序的內存分配和釋放。 每當您建立新對象時,公共語言運行時都會從託管堆爲該對象分配內存。只要託管堆中有地址空間可用,運行時就會繼續爲新對象分配空間。 可是,內存不是無限大的。 最終,垃圾回收器必須執行回收以釋放一些內存。 垃圾回收器優化引擎根據正在進行的分配狀況肯定執行回收的最佳時間。 當垃圾回收器執行回收時,它檢查託管堆中再也不被應用程序使用的對象並執行必要的操做來回收它們佔用的內存。

  垃圾回收的基礎、垃圾回收的性能、被動回收、滯後時間模式、針對共享Web承載優化、垃圾回收通知、應用程序域資源監控、弱引用。請參考此處

小結:

  時間問題,垃圾回收就偷個懶了,O(∩_∩)O~。

  垃圾回收的目的:提升內存利用率。

  垃圾回收器,只回收託管堆中的內存資源。不回收其餘資源(數據庫鏈接、文件句柄、網絡端口等)

  什麼樣的對象纔會被回收?

  沒有變量引用的對象。沒有變量引用的對象,表示能夠被回收(null)。

  什麼時間回收?

  不肯定,當程序須要新內存的時候開始執行回收。

  GC.Collect();//手動調用垃圾回收器。不建議使用,垃圾回收時會暫停一下(很是短暫)讓程序區自動調用GC。

  垃圾回收器中"代"的概念:

  共3代:第0代、第1代、第2代。各代的回收頻率:第0代最高,其次第1代,再次第2代。也就是說越老的對象生存概率越大。

  除了內存資源外的其餘資源怎麼辦? Dispose()

  弱引用:WeakReference,對於建立比較耗時的對象可使用弱引用。

  弱引用例子:

  person p=new person();

  p.Age=13;

  WeakReference wk=WeakReference(p);//弱引用

  p=null;//當執行完這句話的時候,垃圾回收能夠去回收p對象。一般弱引用還能夠訪問到p。

  object pnew=wk.Target;

  //垃圾回收不知道何時進行,因此存在漏洞。通常不用isLive。

  if(pnew != null)

  {Console.WriteLine(((Person)pnew).Age);}

  else{Console.WriteLine("對象已經被回收!")};

  //弱引用在大括號內有效。

  弱引用小結:

  弱引用通常存在那些建立是比較耗時的對象。例如打開數據庫取出比較多的數據時,只要在垃圾回收以前,弱引用對該對象仍是有效地。弱引用就至關於存一個源對象的索引,只要源對象沒被垃圾回收進行回收,弱引用就能夠引用。

相關文章
相關標籤/搜索