C#詳解類型,變量與對象


本節內容:

1.什么是類型(Type

2.類型在C#語言中的作用

3.C#語言的類型系統

4.變量、對象與內存

 

1.什么是類型(type

類型又名數據類型(Date Type),是數據在內存中存儲時的“型號”,小內存容納大數據會丟失精確度、發生錯誤大內存存納小尺寸數據會導致浪費,編程語言的數據類型與數據的數據類型不完全相同

 

1.2.強類型語言(保證了數據的完整性)(數據受到數據類型的約束嚴格)與弱類型語言(靈活性與危險性並存)(保證數據的正確性)的比較

*C語言中這里的if里面得的值不為0其他都為真,即使不是bool類型也可通過編譯,故為弱類型;

*相對的C#if條件里面必須為bool類型的值,否則編譯不過去。

C語言舉例-if條件;JavaScript示例:動態類型(極弱類型語言);C#語言對弱類型?/動態類型的模擬

 

2.類型在C#語言中的作用

2.1.一個C#類型中所包含的信息有:

①存儲此類型變量所需的內存空間大小;

②此類型值可表示的最大、最小值范圍;

③此類型所包含的成員(如方法、屬性、事件等);

④程序運行的時候,此類型的變量在分配內存的什么位置;

Stack簡介:比較小,比較快,用於方法(函數)調用,(裝多了會爆);

第一種情況為:算法沒寫好,函數調用過多,棧就爆了;

第二種情況:程序有錯誤,不小心在棧上分配了太多的內存,棧就爆了;

稱為:Stack overflow

Heap簡介:即堆,比較大,用於存儲對象(實例就放在堆里面),如果忘記回收對象會造成內存浪費,這種浪費學名叫做:內存泄漏。

使用Performance Monitor查看進程的堆(Heap)內存使用量;

關於內存泄漏:C#中存在垃圾回收機制,對象沒人用了,有垃圾回收機制自動回收對象的內存。不用像java一樣需要手動釋放內存,換句話說C#較安全比C++安全得多。

⑤此類型所允許的操作符(運算)如: double result = 3 / 4;結果為0

double result = 3.0 / 4.0;結果為0.75

⑥靜態的程序指的是沒有在運行的程序。

程序的靜態期(編輯器和編譯器),動態期(運行期):靜態的分析代碼,動態的調試程序

可以這么說靜態的程序是裝在硬盤里的,動態的程序是裝在內存里的。

雙擊一個應用程序(exe)就是一個把存儲在硬盤里的靜態程序動態加載到內存的過程。

Process(進程)概念介紹:一個程序從硬盤加載到內存開始執行之后,就形成一個進程,換句話說就是這個程序正在運行的實例。進程名與(exe)程序文件名字相同,且每個進程都有一個pidProcess ID

Windows+R鍵可以打開運行窗口,輸入perfmonPerformance Monitor)進入性能監視器,打開性能監視器窗口,該窗口默認監視總的進程,可以點“x”在“+”號中添加具體的進程,監視某一程序的內存占比變化。

 

3.C#語言的類型系統

C#五大數據類型

類(Class):如WindowsFormConsole

結構體(Structures):如Int32Int64SingleDouble

如:在intf12查看定義:public struct Int32 : IComparable

枚舉(Enumerations):如HorizontalAlignmentVisbility

例如:public enum FormWindowState

    {

         //默認大小的窗口。

        Normal = 0,

        //最小化的窗口。

        Minimized = 1,

       //最大化的窗口。

        Maximized = 2,

}

接口(Interfaces

委托(Delegates

C#類型的派生譜系:

Object:引用類型(Reference Type)和值類型(Value Type

引用類型:類、接口、委托

值類型:結構體、枚舉

 

最右邊的分類上下來看可以分為三組:第一組(與引用類型相關)objectstring(這兩個關鍵詞基類(class)為本身)與class interfacedelegate(這三個關鍵字不是具體的數據類型f12找不到定義的,而是運用這三個關鍵詞去創建他們的數據類型);

第二組(與值類型相關):橫線以上:對應的是真正數據類型;橫線以下與第一組的橫線以下的三個一樣,都是去定義各自的類型,沒有基類型。

第三組:truefalsebool類型的返回值;void表示不需要返回值,null表示一個引用變量里面的值是空的不屬於任何數據類型;vardynamic是用來聲明變量的(以后會用到)。

(藍色的字體表示為現成的數據類型,而且十分常用,甚至被歸為關鍵字了;其次這些數據類型都是基本數據類型(即別的類型都是拿這些數據類型去構成的))

 

4.變量、對象與內存

*值類型與引用類型的內存存儲方式是不同的,不分清將會造成很大錯誤!

①什么是變量

表面上來看(從C#代碼的上下文行文來看),變量的用途是存儲數據。

實際上,變量表示了存儲位置(例如int x=100;x只是一個標簽指向一個地址,數據100就存儲在這個地址里面),並且每一個變量都有一個存儲類型,以決定什么類型的值能夠存入變量。*即變量名稱表示(對應着)變量的值在內存中的存儲位置

*認識一個事物是由淺入深,由表及里,由現象到本質的過程。

變量一共有7種:

靜態變量(static),實例變量(也叫非靜態變量)(成員變量、字段),數組元素、值參數、引用參數、輸出形參、局部變量。

狹義的變量指的是局部變量,因為其它種類的變量都有自己的約定名稱。

  簡單地講,局部變量就是方法體(函數體)里面聲明的變量。

變量的聲明:

有效的修飾符組合(可無) 類型 變量名 初始化器(可無)如:int x

*總結:變量=以變量名所對應的內存地址為起點,以其數據類型所要求的存儲空間為長度的一塊內存區域

②值類型的變量:

byte/sbyte/short/ushort為例:

值類型沒有實例,所謂“實例”與變量合二為一(因為是結構體struct)。

值類型變量的存儲如:byte b;b=100;這兩條語句作用為:首先確定byte數據類型需要的存儲空間大小,然后去內存中找可以使用的(空的)內存地址,找到內存地址后,就把變量名與該內存地址對應起來,再把100轉化為2進制數據寫進該地址內存中。

③引用類型的變量與實例:

引用類型變量與實例的關系:引用類型變量里存儲的數據是對象(實例)的內存地址解釋如下:存儲引用類型變量與實例時如:

*創建Student類的引用類型變量:Student stu;創建后便去內存(因為其為局部變量故由棧分配內存)中尋找空閑的內存並分得4個字節的內存空間(凡是引用類型固定分配4字節)

*然后創建Student類的實例:new Student();這個時候要去找空閑的堆內存,找 到之后開始分配內存,這時需要計算需要多大的內存(類中的各種數據占內存的總 和),分完之后還要在該內存塊內部進行分組:這塊內存是存儲哪種數據類型的, 那塊屬於哪種數據類型...

*最后將其賦值給引用類型變量(把氣球給孩子):stu = new Student();此時在內 存中把創建類的實例時分配到的內存地址(內存地址是一個編號不是二進制數)轉化為二進制數,並將該二進制數存儲到創建Student類引用類型變量stu時分配到的4個字節的內存空間里面(按高低原則)。完成引用類型變量的存儲。

 

這樣就可以解釋兩個不同的引用類型變量來引用同一個實例的情況(兩個小朋友分別用自己的兩根繩子牽着同一個氣球),如下:

{

Student stu1

Student stu2

stu1=new Student();

Stu2=stu1;

}

④變量的默認值(局部變量(main函數外如類里面的變量)一旦創建后在內存塊中全部刷為0);注意本地變量不能沒有初始值(main函數里的變量),例如:

所謂的本地變量不能沒有初始值,指的是不能沒有初始值就被其他方法調用,如main函數中的如下語句:

Int x;

Console.WriteLind(x);

由於本地變量x沒有初始值就被Console類的WriteLine方法調用了故會報錯。

⑤常量(值不可改變的變量)

⑦局部變量是在Stack(棧)上分配內存的(其他一般在堆中分配)

⑥裝箱與拆箱(Boxing&Unboxing

補充說明:object是類可以派生出:數值類型和引用類型,但本身是類而類屬於引用類型,所以object屬於引用類型:內存空間存儲被引用對象的地址。其定義為:

public class Object

{

public Object();

}

可見object一般當做引用類型使用。

 

*裝箱:當引用變量引用上的數據的時候就要進行裝箱,先把被引用的數據(下面指int x)拷貝一份,封裝成一個實例,放在堆上的空閑內存中。

例如 {

int x=100//注意局部變量是在棧上分配內存的

    object obj

    obj=x

}

為了使 obj=x”成立:obj為引用型變量分配到的4個字節內存存的是地址,如果直接把數值型變量x內存里存的數據復制給obj的內存空間,則obj會把內存空間里的數據當做是地址,然后去引用該地址的數據,顯然錯誤。

正確做法為:先在上開辟兩塊內存空間給int xobj(局部變量)再去中創建int 類型x的內存空間並把內容復制到里面去,然后把該段內存首地址轉化為2進制數在復制給在obj的內存,這個過程使“obj=x;語句合法的內存操作”叫做裝箱。

*即把棧上的值類型的數據封裝成一個object類型的實例放在堆上叫做裝箱

 

*拆箱:例如 {

int x=100

    object obj

    obj=x

Int y=[int]obj;

}

為了使 Int y=[int]obj;(在堆內把obj的數據取出來)”成立:先在棧內存中找到空閑的內存開辟一個4字節(因為yint型)的存儲空間存放數值類型變量y,然后將某塊內存中存放的obj對象數據的按int32格式把數據(轉換)復制到y變量的內存空間中。

*即把堆中obj實例里面的值按要求拆成目標數據類型存儲到棧上y(目標數據類型)的內存空間中。

 

*裝箱裝地址,拆箱按要求拆出數據(如:int y=obj;obj要按int32的格式拆出數據)

*裝箱和拆箱會損失程序的性能,慎用。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM