當前位置:
首頁 > 最新 > C#類型本質-進階編程篇(一)

C#類型本質-進階編程篇(一)

這是我的第一篇講解編程技巧的教程文章,不管是措辭還是排版,肯定有諸多不完善的地方,還請各位多多擔待。對於專業知識來說,因為技術是會存在過時的,所以我也沒有辦法保證所講解的內容完全是正確的,而且我覺得我理解的還不夠深,將來的某一天可能也會回頭修正現在的表述,說明,也就是傳說中的打臉,但是這件事情總是要有個開端的,既然想到這個問題,就何不從現在開始去做呢。

這個系列的文章在專業性方面,我會儘可能的講解我清楚的,如果我自己也不清楚,我會參考一些書籍,如果還沒有書籍參考,那我就通過自己的經驗來做了,大體上我會為我的教程負責的,希望可以幫到目前正在編程或將要編程的你們,你們是最可愛的人。

下面進入正題,也就是進階編程篇的第一篇,C#類型的本質,本來本章也想了另一個名稱:你真的了解類型嗎?後來覺得太裝B了,所以仍然使用了C#本質的標題。要進入本片學習,我需要假定您已經看過基礎的C#編程書了,至少會簡單的拖控制項開發了,可以顯示顯示的數據,也會自定義控制項的開發。正式進入提高階段,如果您沒有基礎的知識,推薦您去學習《C#從人們到精通》這本書了,OK,馬上進入正題。

我們都知道日常使用的類型,比如byte,int,long,等,除了這些值類型之外,還有各種庫提供的類和我們自己開發的類。比如

Timer time1=new Timer();

我們非常習慣使用這些類型來創建示例,並且使用的很自然,比如

int i = 0;

OK,那我們來講解第一個問題,不知道你有沒有發現,在visual studio開發程序的時候,對於我們熟悉的int類型,IDE提供了兩套類型模式,比如int和Int32,根據查看MSDN的說法,兩者是一致的,如果真的是一致的,又為什麼提供兩種命名方式呢,這個問題的解釋有點複雜,關係到程序運行的機制,而C#只是一種語言,一種編寫CLR程序的語言,VS將我們用C#編寫的程序翻譯成了IL中間語言的程序,因為CLR和IL語言是無縫集成的,這樣我們的程序才可以在CLR上運行,可能有些人會疑問,我們寫的程序不應該是windows來運行的嗎,本質上確實是如此,由windows來運行CLR,CLR來運行託管程序。那麼問題來了,IL中間語言本身就直接支持了一套類型,比如Int32,Int16,Int64,等等,這套類型叫做基元類型,在微軟開發C#編譯器的時候,腦子一熱,覺得原來的名稱不太符合C語言的習慣,所以就額外提供了一套新的類型命名,int,short,long等,在編譯的時候直接會編譯成CLR支持的類型,至於在使用習慣上,根據自己的習慣選擇,有些書會比較推薦CLR的標準。

第二個有意思的問題是如果我寫了個靜態的int變數,就可以在程序的任何地方(可以在不同的線程)進行引用,獲取,設置值而不用擔心其他問題,比如競爭問題。不要思考也還好,一旦要去考慮這個問題的答案,背後就隱藏了一個極大的秘密,對象數據的本質。我們在實例化一個對象後,如下

int i=0;

這行代碼不僅僅只是生成了一個4個位元組的變數數據,準確的說,對象i的數據部分確實是4個位元組而已,但是對象本身絕對不是4個位元組的問題,它還有另外兩個非常重要的數據對象,叫同步索引塊和類型對象塊,而其中的同步索引塊就控制了類型在同一瞬間只能進行一次設置,我們知道數據都是01組成,我們在執行i=0xffffff時,在另一個地方剛好獲取i的值,這樣就避免了萬一設置到一半(i=0xff0000),我們就獲取到了錯誤的值的可能性。

第三個有意思的問題是對象其實知道它自己的類型,還是拿上述的

int i=0;

作為說明對象,我們可以調用i.GetType()來獲取i本身的類型,你可能會覺得這玩意到底有什麼用,我自己定義的i我還不知道他是什麼類型嗎?

事實上用處大了,我先說明有什麼用處,在說明原因。正是因為對象自己知道自己的類型,才能執行一些類型的轉換,強制轉換也好,隱式轉換也罷,C#所有的轉換建立在這個基礎之上的,再看下面的代碼:

int i=0;

object obj=(object)i;

string m=(string)obj;

在第二行代碼中,因為編譯器知道object是所有類的基類,所以可以轉化,但是obj對象的類型真的是object嗎?答案是不一定的,因為object是所有類的基類,所以obj理論上來說可以是任何類型,此處你可以獲取類型來確認,obj其實是int類型。正是因為int類型和string類型不存在繼承關係,所以第三行代碼報錯。

第四個有意思的問題是,我們都知道int使用了四個位元組,byte使用了一個位元組,但是如果我問bool使用了幾個位元組?還是一個位而已?這個問題就需要實踐出真知了,我們就寫代碼來判斷吧,聲明一個類

[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]

public class SomeValType

{

[System.Runtime.InteropServices.FieldOffset(0)]

public byte ValueByte = 0;

[System.Runtime.InteropServices.FieldOffset(0)]

public int ValueInt = 0;

[System.Runtime.InteropServices.FieldOffset(0)]

public bool ValueBool = false;

}

然後在其他地方使用斷點查看,代碼如下:

SomeValType value = new SomeValType();

value.ValueInt = -1;

value.ValueBool = false;

這時候監視查看到bool對象隻影響了一個位元組。這種技術允許數據區域重疊,你改變一個變數的時候也會影響其他變數,有些情況會比較適合,比如是一個IP類型,由四個位元組組成,一個int就能表示,但也允許設置單個的網段。

第五個有意思的類型就是string了,看似平凡的字元串,背後的東西多的不得了,字元串類型有個非常大的特性,它是不易變的。如果你定義了一個字元串string m="123456";,它就傻傻的呆在一個內存塊中,不會變化,直到被清除為止,所以針對如下代碼怎麼去理解:

string s = "";

for (int i = 0; i < 10000; i++)

{

s += "1";

}

s的最終結果是10000個1組成的字元串,但是中間有一萬次的重新分配和刪除,實際的性能非常差,應該避免這種情況。

關於string類型最難的就是本地化了,雖然大多數的程序員都不太關心這個問題,因為大多數的程序都只是給一個特定語言使用的,比如說中文,比如說英文,所以此處就簡單的提個例子,即時兩個看著不同的string,因為語言文化不一致,在比較相同的時候也是可能相同的。

第一篇文章就大致寫到這裡,以後有機會再補充。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!

TAG: |

您可能感興趣

XSD 雜項 數據類型
自製Monkey編程語言編譯器:增加數組操作API和Mapsh數據類型
RADIX DLT——一種全新類型的加密貨幣
類型論:一類新的數學
R語言:數據類型(向量、數組、矩陣、 列表和數據框)
一文詳解 React 組件類型
GTA5MOD安裝視頻教程 全部類型安裝教程
XSD 字元串 數據類型
Mariadb學習總結(三):數據類型
影評:類型文學的文學化——評《齊瑪的作品》
MATLAB入門篇 數值類型
典型案例3/10 (類型:體育類,學校:丹佛大學)
編程教程:淺談C#的隱式顯式類型轉換
《動物世界》:作者、類型與改編
XML DOM 節點類型
NBA球衣等級類型詳解
窗帘軌道的基本類型
XSD 數值數據類型
opencv Mat類型和BYTE*指針類型互轉
Kotlin 基本數據類型