學習劉鐵猛老師《C#語言入門詳解》視頻,針對其中重點知識點進行總結,
1、什么是型別?
型別又稱為資料型別(Data Type),資料型別在資料結構中的定義是一個值的集合以及定義在這個值集上的一組操作,
可以簡單理解為資料在記憶體中存盤的“型號”;小記憶體容納大尺寸資料會丟失精準度,發生錯誤;而大記憶體容納小尺寸資料會導致浪費,
還應注意編成語言的資料型別與數學中的資料型別不完全相同,例如數學中 3/4=0.75 而在C# 語言中 3 /4 =0,
不同的編程語言對資料型別的約束程度不一樣,所以有強型別編程語言和弱型別編程語言的區分,
變數是用來存盤值得所在處,它們有名字和資料型別,變數的資料型別決定了如何將代表這些值的位存盤到計算機的記憶體中,
我們都知道,計算機的世界是二進制的,僅僅用0和1就構建了所有的表達,計算機用來存盤0或者1的單位就是位(bit),8個位組成一個位元組(byte),
2、資料型別在C#語言中的作用
一個C#型別中所包含的資訊有:
- 存盤此型別變數所需的記憶體空間大小 如 int 型別需要4個位元組也就是4*8=32位進行存盤
- 此型別的值可表示的最大、最小值范圍 sbyte占一個位元組8位,s前綴表示帶符號位,取值范圍-128到127,byte占一個位元組,不帶符號位,取值范圍位0-255,
- 此型別所包含的成員(如方法、屬性、事件等) 可以用于ide的錯誤識別和反射時動態呼叫
- 此型別由何基類派生而來
- 程式運行的時候,此型別的變數在分配在記憶體的什么位置(堆疊或堆)
- 此型別所允許的操作(運算)
3、程式的記憶體使用分析
- Stack簡介:函式呼叫使用,函式呼叫實際可以理解位堆疊幀的入堆疊出堆疊操作,空間較小,一般1-2M
- Stack overflow 空間較小所以會出現堆疊空間溢位的情況,例如遞回函式未正常結束,
- Heap簡介:用來存盤物件(實體)使用,空間較大,可以達到數G
- 使用Perfomance Monitor觀察記憶體使用情況
- 關于記憶體泄漏 未使用的物件未賦值為null導致垃圾收集器未處理,導致空間浪費,這稱為記憶體泄漏,
這里給出觀察記憶體使用情況的一個樣例,新增的wpf程式,使用Winform程式也是可行的,
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Windows; 7 using System.Windows.Controls; 8 using System.Windows.Data; 9 using System.Windows.Documents; 10 using System.Windows.Input; 11 using System.Windows.Media; 12 using System.Windows.Media.Imaging; 13 using System.Windows.Navigation; 14 using System.Windows.Shapes; 15 16 namespace HeapSample 17 { 18 /// <summary> 19 /// MainWindow.xaml 的互動邏輯 20 /// </summary> 21 public partial class MainWindow : Window 22 { 23 public MainWindow() 24 { 25 InitializeComponent(); 26 } 27 28 List<Window> winList; 29 30 private void Btn_Consume_Click(object sender, RoutedEventArgs e) 31 { 32 winList = new List<Window>(); 33 for (int i = 0; i < 20000; i++) 34 { 35 Window wd = new Window(); 36 winList.Add(wd); 37 } 38 } 39 40 private void Btn_ClearHeap_Click(object sender, RoutedEventArgs e) 41 { 42 winList.Clear(); 43 } 44 } 45 }
至于Perfomance Monitor觀察記憶體使用情況,可以查看 https:////www.cnblogs.com/FreeLoopPowter/p/12298482.html ,
4、C# 資料型別系統
C#的五大資料型別
- 類(class):如 Form,Window,Console.String
- 結構體(structres):如 Int32,Int64,SIngle,Double
- 列舉(Enumerations):如Visibility,WindoState
- 介面(Interfaces)
- 委托(Delegate)
C#型別的派生譜系

這里順帶提一點,我們經常在編輯器中使用結構體時,例如定義一個32位的整型變數時,我們基本使用 int a=5; 這樣的形式,這并不是前面說的結構體型別包含的內容,為啥沒有報錯呢?
這是由于某些資料型別如此常用,以至于許多編輯器允許代碼以簡化語法來操縱它們(也叫關鍵字),這種語法不僅增強了代碼的可讀性和書寫的方便性,生成的IL代碼還與使用對應的FCL類別庫中的型別一致,
這類編譯器能直接支持的型別稱為 基元型別,基元型別直接映射到Framework類別庫(FCL)中存在的型別,可以通過按 F12 查看定義,就可以看到映射的FCL型別,
查看CLR Via C#一書,發現其對值型別和參考型別的闡述非常明了,還包括了對值型別和參考型別記憶體分配的講解,這里選取重要內容進行記錄,方便自己后續溫習,對資料型別的記憶體分配情況的分析有利于后續理解方法的傳值引數、參考引數、輸出引數的理解,
CLR支持兩種型別:參考型別和值型別,雖然FCL的大多數型別都是參考型別,但程式員使用最多的還是值型別,參考型別總是從托管堆中分配,C#的new 運算子回傳物件記憶體地址——即指向物件資料的記憶體地址,使用參考型別必須留意性能問題,首先認清楚以下四個事實,
- 記憶體必須從托管堆分配,
- 堆上分配的每個物件都有一些額外成員,
- 物件中的其他欄位(為欄位而設)總是設為零,
- 從托管堆分配物件時,可能強制執行一次垃圾回收,(當垃圾回收器發現記憶體不夠時會強制執行一次垃圾回收)
如果所有型別都是參考型別,應用程式的性能將顯著下降,設想每次使用 Int32 時都進行一次記憶體分配,性能會收到多么大的影響!為了提升簡單和常用的資料型別的性能,CLR提供了名為“值型別”的輕量級型別,值型別的實體一般是在執行緒堆疊上分配(雖然也可作為欄位嵌入參考型別的物件中),在代表值型別實體的變數中不包含指向實體的指標,變數中包含了實體本身的欄位,由于變數已包含了實體的欄位,所以操作實體中的欄位不需要提取指標,值型別的實體不受垃圾回收器的控制,因此,值型別的使用緩解了托管堆的壓力,并減少了應用程式生存期間的垃圾回收次數,
下面給出一個示例,結合圖示講解值型別和參考型別的區別,參考型別變數對物件實體的參考實際上是以在堆疊中分配的參考型別變數存放堆中實體的起始記憶體地址來實作的,
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace RefTypeAndValueTypeApp 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //在堆上分配空間 14 SomeRef r1 = new SomeRef(); 15 //在堆疊上分配空間 16 SomeValue v1 = new SomeValue(); 17 r1.x = 5;//提取指標,給指標參考的物件賦值 18 v1.x = 5;//在堆疊上修改,由0修改為5 19 Console.WriteLine(r1.x);//顯示 "5" 20 Console.WriteLine(v1.x);//同樣顯示 "5" 21 //以上記憶體分配情況見圖左邊 22 23 //只復制參考(指標) 24 SomeRef r2 = r1; 25 //在堆疊上分配并復制成員 26 SomeValue v2 = v1; 27 r1.x = 8;//r1.x 和 r2.x 都會改變 28 v1.x = 9;//v2.x會改變 v1.x不會改變 29 Console.WriteLine(r1.x);//顯示 "8" 30 Console.WriteLine(r2.x);//同樣顯示 "8" 31 Console.WriteLine(v1.x);//顯示 "9" 32 Console.WriteLine(v2.x);//顯示 "5" 33 //以上部分程式執行的記憶體分配情況見圖右側 34 35 //讓控制臺等待輸入,有輸入后才終止 36 Console.ReadKey(); 37 } 38 } 39 /// <summary> 40 /// 參考型別 41 /// </summary> 42 class SomeRef 43 { 44 public Int32 x; 45 } 46 47 /// <summary> 48 /// 值型別 49 /// </summary> 50 struct SomeValue 51 { 52 public Int32 x; 53 } 54 }

書寫這篇隨筆的主要目的是自己溫習和防遺忘,本著分享的心態公開,如有不妥之處,還請指出,相互交流,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/62018.html
標籤:其他
