裝箱拆箱還是別名
許多 C#NET 的書上都有介紹 int > Int 是一個裝箱的過程反之則是拆箱的過程許多其它變量類型也是如此如short <> Intlong <> Int 等對於一般的程序員來說大可不必去了解這一過程因為這些裝箱和拆箱的動作都是可以自動完成的不需要寫代碼進行干預但是我們需要記住這些類型之間的關系所以我們使用別名來記憶它們之間的關系
C# 是全面向對象的語言比 Java 的面向對象都還徹底——它把簡單數據類型通過默認的裝箱動作封裝成了類IntIntInt 等就是相應的類名而那些我們熟悉的簡單易記的名稱如 intshortlong 等我們就可以把它稱作是 IntIntInt 等類型的別名那麼除了這三種類型之外還有哪些類有別名呢?常用的有如下一些
bool > SystemBoolean (布爾型其值為 true 或者 false)
char > SystemChar (字符型占有兩個字節表示 個 Unicode 字符)
byte > SystemByte (字節型占 字節表示 位正整數范圍 ~ )
sbyte > SystemSByte (帶符號字節型占 字節表示 位整數范圍 ~ )
ushort > SystemUInt (無符號短整型占 字節表示 位正整數范圍 ~ )
uint > SystemUInt (無符號整型占 字節表示 位正整數范圍 ~ )
ulong > SystemUInt (無符號長整型占 字節表示 位正整數范圍 ~ 大約 的 次方)
short > SystemInt (短整型占 字節表示 位整數范圍 ~ )
int > SystemInt (整型占 字節表示 位整數范圍 到 )
long > SystemInt (長整型占 字節表示 位整數范圍大約 ( 的 ) 次方 到 的 次方)
float > SystemSingle (單精度浮點型占 個字節)
double > SystemDouble (雙精度浮點型占 個字節)
我們可以用下列代碼做一個實驗
private void TestAlias() {
// thistextBox 是一個文本框類型為 SystemWindowsFormsTextBox
// 設計中已經將其 Multiline 屬性設置為 true
byte a = ; char b = a; short c = ;
int d = ; long e = ; uint f = ; bool g = true;
thistextBoxText = ;
thistextBoxAppendText(byte > + aGetType()FullName + \n);
thistextBoxAppendText(char > + bGetType()FullName + \n);
thistextBoxAppendText(short > + cGetType()FullName + \n);
thistextBoxAppendText(int > + dGetType()FullName + \n);
thistextBoxAppendText(long > + eGetType()FullName + \n);
thistextBoxAppendText(uint > + fGetType()FullName + \n);
thistextBoxAppendText(bool > + gGetType()FullName + \n);
}在窗體中新建一個按鈕並在它的單擊事件中調用該 TestAlias() 函數我們將看到運行結果如下
byte > SystemByte
char > SystemChar
short > SystemInt
int > SystemInt
long > SystemInt
uint > SystemUInt
bool > SystemBoolean
這足以說明各別名對應的類!
數值類型之間的相互轉換
這裡所說的數值類型包括 byte short int long fload double 等根據這個排列順序各種類型的值依次可以向後自動進行轉換舉個例來說把一個 short 型的數據賦值給一個 int 型的變量short 值會自動行轉換成 int 型值再賦給 int 型變量如下例
private void TestBasic() {
byte a = ; short b = a; int c = b;
long d = c; float e = d; double f = e;
thistextBoxText = ;
thistextBoxAppendText(byte a = + aToString() + \n);
thistextBoxAppendText(short b = + bToString() + \n);
thistextBoxAppendText(int c = + cToString() + \n);
thistextBoxAppendText(long d = + dToString() + \n);
thistextBoxAppendText(float e = + eToString() + \n);
thistextBoxAppendText(double f = + fToString() + \n);
}譯順利通過運行結果是各變量的值均為 當然它們的類型分別還是 SystemByte 型……SystemDouble 型現在我們來試試如果把賦值的順序反過來會怎麼樣呢?在 TestBasic() 函數中追加如下語句
int g = ;
short h = g;
thistextBoxAppendText(h = + hToString() + \n);
結果編譯報錯
G:\Projects\Visual C#\Convert\Formcs(): 無法將類型int隱式轉換為short
其中Formcs 的 行即 short h = g 所在行
這個時候如果我們堅持要進行轉換就應該使用強制類型轉換這在 C 語言中常有提及就是使用(類型名) 變量名形式的語句來對數據進行強制轉換如上例修改如下
short g = ;
byte h = (byte) g; // 將 short 型的 g 的值強制轉換成 short 型後再賦給變量 h
thistextBoxAppendText(h = + hToString() + \n);
編譯通過運行結果輸出了 h = 轉換成功
但是如果我們使用強制轉換就不得不再考慮一個問題short 型的范圍是 ~ 而 byte 型的范圍是 ~ 那麼如果變量 g 的大小超過了 byte 型的范圍又會出現什麼樣的情況呢?我們不妨再一次改寫代碼將值改為 比 大
short g = ; // = +
byte h = (byte) g;
thistextBoxAppendText(h = + hToString() + \n);
編譯沒有出錯運行結果卻不是 h = 而是 h =
因此我們在進行轉換的時候應當注意被轉換的數據不能超出目標類型的范圍這不僅體現在多字節數據類型(相對如上例的 short) 轉換為少字節類型(相對如上例的 byte) 時也體現在字節數相同的有符號類型和無符號類型之間如將 byte 的 轉換為 sbyte 就會溢出這方面的例子大同小異就不詳細說明了
字符的 ASCII 碼和 Unicode 碼
很多時候我們需要得到一個英文字符的 ASCII 碼或者一個漢字字符的 Unicode 碼或者從相關的編碼查詢它是哪一個字符的編碼很多人尤其是從 VB 程序序轉過來學 C# 的人會報怨 C# 裡為什麼沒有提供現成的函數來做這個事情——因為在 VB 中有 Asc() 函數和 Chr() 函數用於這類轉換
但是如果你學過 C你就會清楚我們只需要將英文字符型數據強制轉換成合適的數值型數據就可以得到相應的 ASCII 碼反之如果將一個合適的數值型數據強制轉換成字符型數據就可以得到相應的字符
C# 中字符的范圍擴大了不僅包含了單字節字符也可以包含雙字節字符如中文字符等而在字符和編碼之間的轉換則仍延用了 C 語言的做法——強制轉換不妨看看下面的例子
private void TestChar() {
char ch = a; short ii = ;
thistextBoxText = ;
thistextBoxAppendText(The ASCII code of \ + ch + \ is: + (short) ch + \n);
thistextBoxAppendText(ASCII is + iiToString() + the char is: + (char) ii + \n);
char cn = 中; short uc = ;
thistextBoxAppendText(The Unicode of \ + cn + \ is: + (short) cn + \n);
thistextBoxAppendText(Unicode is + ucToString() + the char is: + (char) uc + \n);
}它的運行結果是
The ASCII code of a is:
ASCII is the char is: A
The Unicode of 中 is:
Unicode is the char is: 城
從這個例子中我們便能非常清楚的了解——通過強制轉換可以得以字符的編碼或者得到編碼表示的字符如果你需要的不是 short 型的編碼請參考第 條進行轉換即可得到 int 等類型的編碼值
數值字符串和數值之間的轉換
首先我們得搞明白什麼是數值字符串我們知道在 C# 中字符串是用一對雙引號包含的若干字符來表示的如 而 又相對特殊因為組成該字符串的字符都是數字這樣的字符串就是數值字符串在我們的眼中這即是一串字符也是一個數但計算機卻只認為它是一個字符串不是數因此我們在某些時候比如輸入數值的時候把字符串轉換成數值而在另一些時候我們需要相反的轉換
將數值轉換成字符串非常簡單因為每一個類都有一個 void ToString() 方法所有數值型的 void ToString() 方法都能將數據轉換為數值字符串如 ToSting() 就將得到字符串
那麼反過來將數值型字符串轉換成數值又該怎麼辦呢?我們仔細查找一下會發現 short int float 等數值類型均有一個 static Parse() 函數這個函數就是用來將字符串轉換為相應數值的我們以一個 float 類型的轉換為例 float f = floatParse(); 其結果 f 的值為 F當然其它的數值類型也可以使用同樣的方法進行轉換下面的例子可以更明確的說明轉換的方法
private void TestStringValue() {
float f = F;
string str = ;
thistextBoxText = ;
thistextBoxAppendText(f = + fToString() + \n);
if (intParse(str) == ) {
thistextBoxAppendText(str convert to int successfully);
} else {
thistextBoxAppendText(str convert to int failed);
}
}運行結果
f =
str convert to int successfully
字符串和字符數組之間的轉換
字符串類 SystemString 提供了一個 void ToCharArray() 方法該方法可以實現字符串到字符數組的轉換如下例
private void TestStringChars() {
string str = mytest;
char[] chars = strToCharArray();
thistextBoxText = ;
thistextBoxAppendText(Length of \mytest\ is + strLength + \n);
thistextBoxAppendText(Length of char array is + charsLength + \n);
thistextBoxAppendText(char[] = + chars[] + \n);
}例中以對轉換轉換到的字符數組長度和它的一個元素進行了測試結果如下
Length of mytest is
Length of char array is
char[] = t
可以看出結果完全正確這說明轉換成功那麼反過來要把字符數組轉換成字符串又該如何呢?
我們可以使用 SystemString 類的構造函數來解決這個問題SystemString 類有兩個構造函數是通過字符數組來構造的即 String(char[]) 和 String[char[] int int)後者之所以多兩個參數是因為可以指定用字符數組中的哪一部分來構造字符串而前者則是用字符數組的全部元素來構造字符串我們以前者為例在 TestStringChars() 函數中輸入如下語句
char[] tcs = {t e s t m e};
string tstr = new String(tcs);
thistextBoxAppendText(tstr = \ + tstr + \\n);
運行結果輸入 tstr = test me測試說明轉換成功
實際上我們在很多時候需要把字符串轉換成字符數組只是為了得到該字符串中的某個字符如果只是為了這個目的那大可不必興師動眾的去進行轉換我們只需要使用 SystemString 的 [] 運算符就可以達到目的請看下例再在 TestStringChars() 函數中加入如如下語名
char ch = tstr[];
thistextBoxAppendText(\ + tstr + \[] = + chToString());
正確的輸出是 test me[] = t經測試輸出正確
字符串和字節數組之間的轉換
如果還想從 SystemString 類中找到方法進行字符串和字節數組之間的轉換恐怕你會失望了為了進行這樣的轉換我們不得不借助另一個類SystemTextEncoding該類提供了 bye[] GetBytes(string) 方法將字符串轉換成字節數組還提供了 string GetString(byte[]) 方法將字節數組轉換成字符串
SystemTextEncoding 類似乎沒有可用的構造函數但我們可以找到幾個默認的 Encoding即 EncodingDefault(獲取系統的當前 ANSI 代碼頁的編碼)EncodingASCII(獲取 位 ASCII 字符集的編碼)EncodingUnicode(獲取采用 LittleEndian 字節順序的 Unicode 格式的編碼)EncodingUTF(獲取 UTF 格式的編碼)EncodingUTF(獲取 UTF 格式的編碼) 等這裡主要說說 EncodingDefault 和 EncodingUnicode 用於轉換的區別
在字符串轉換到字節數組的過程中EncodingDefault 會將每個單字節字符如半角英文轉換成 個字節而把每個雙字節字符如漢字轉換成 個字節而 EncodingUnicode 則會將它們都轉換成兩個字節我們可以通過下列簡單的了解一下轉換的方法以及使用 EncodingDefault 和 EncodeingUnicode 的區別
private void TestStringBytes() {
string s = C#語言;
byte[] b = SystemTextEncodingDefaultGetBytes(s);
byte[] b = SystemTextEncodingUnicodeGetBytes(s);
string t = t = ;
foreach (byte b in b) {
t += bToString() + ;
}
foreach (byte b in b) {
t += bToString() + ;
}
thistextBoxText = ;
thistextBoxAppendText(bLength = + bLength + \n);
thistextBoxAppendText(t + \n);
thistextBoxAppendText(bLength = + bLength + \n);
thistextBoxAppendText(t + \n);
}
運行結果如下不說詳述相信大家已經明白了
bLength =
bLength =
將字節數組轉換成字符串使用 Encoding 類的 string GetString(byte[]) 或 string GetString(byte[] int int) 方法具體使用何種 Encoding 還是由編碼決定在 TestStringBytes() 函數中添加如下語句作為實例
byte[] bs = { };
string ss = SystemTextEncodingASCIIGetString(bs);
thistextBoxAppendText(The string is: + ss + \n);
運行結果為The string is: abcdef
各種數值類型和字節數組之間的轉換
在第 條中我們可以查到各種數值型需要使用多少字節的空間來保存數據將某種數值類型的數據轉換成字節數組的時候得到的一定是相應大小的字節數組同樣需要把字節數組轉換成數值類型也需要這個字節數組大於相應數值類型的字節數現在介紹此類轉換的主角SystemBitConverter該類提供了 byte[] GetBytes() 方法將各種數值類型轉換成字節數組也提供了 ToIntToIntToIntToUIntToSignleToBoolean 等方法將字節數組轉換成相應的數值類型
由於這類轉換通常只是在需要進行較細微的編碼/解碼操作時才會用到所以這裡就不詳細敘述了僅把 SystemBitConverter 類介紹給大家
轉換成十六進制
任何數據在計算機內部都是以二進制保存的所以進制與數據的存儲無關只與輸入輸出有關所以對於進制轉換我們只關心字符串中的結果
在上面的第 條中提到了 ToString() 方法可以將數值轉換成字符串不過在字符串中結果是以十進制顯示的現在我們帶給它加一些參數就可以將其轉換成十六進制——使用 ToString(string) 方法這裡需要一個 string 類型的參數這就是格式說明符十六進制的格式說明符是 x 或者 X使用這兩種格式說明符的區別主要在於 AF 六個數字x 代表 af 使用小寫字母表示而 X 而表示 AF 使用大字字母表示如下例
private void TestHex() {
int a = ;
thistextBoxText = ;
thistextBoxAppendText(a() = + aToString() + \n);
thistextBoxAppendText(a() = + aToString(x) + \n);
thistextBoxAppendText(a() = + aToString(X) + \n);
}運行結果如下
a() =
a() = bc
a() = BC
這時候我們可能有另一種需求即為了顯示結果的整齊我們需要控制十六進制表示的長度如果長度不夠用前導的 填補解決這個問題我們只需要在格式說明符x或者X後寫上表示長度的數字就行了比如要限制在 個字符的長度可以寫成X在上例中追加一句
thistextBoxAppendText(a() = + aToString(X) + \n);
其結果將輸出 a() = BC
現在我們還要說一說如何將一個表示十六進制數的字符串轉換成整型這一轉換同樣需要借助於 Parse() 方法這裡我需要 Parse(string SystemGlobalizationNumberStyles) 方法第一個參數是表示十六進制數的字符串如AB(表示十進制的 ) 等第二個參數 SystemGlobalizationNumberStyles 是一個枚舉類型用來表示十六進制的枚舉值是 HexNumber因此如果我們要將AB轉換成整型就應該這樣寫int b = intParse(AB SystemGlobalizationNumberStylesHexNumber)最後得到的 b 的值是
日期型數據和長整型數據之間的轉換
為什麼要將日期型數據轉換為長整型數據呢?原因很多
但就我個人來說
經常將它用於數據庫的日期存儲
由於各種數據庫對日期型的定義和處理是不一樣的
各種語言對日期型數據的定義的處理也各不相同
因為
我寧願將日期型數據轉換成長整型再保存到數據庫中
雖然也可以使用字符串來保存
但使用字符串也會涉及到許多問題
如區域等問題
而且
它需要比保存長整型數據更多的空間
日期型數據在 C# 中的參與運算的時候應該也是轉換為長整型數據來運算的它的長整型值是自 年 月 日午夜 : 以來所經過時間以 毫微秒為間隔表示時的數字這個數在 C# 的 DateTime 中被稱為 Ticks(刻度)DateTime 類型有一個名為 Ticks 的長整型只讀屬性就保存著這個值如此要從一個 DataTime 型數據得到 long 型值就非常簡單了只需要讀出 DataTime 對象的 Ticks 值即可如
long longDate = DateTimeNowTicks;
DateTime 的構造函數中也提供了相應的從長整型數據構造 DateTime 型數據的函數DateTime(long)如
DateTime theDate = new DateTime(longDate);
但這樣對於很多 VB 程序員來說是給他們出了一道難題因為 VB 中的日期型數據內部是以 Double 型表示的將其轉換為長整型後得到的僅僅是日期而沒有時間如何協調這兩種日期類型呢?
SystemDateTime 提供了 double ToOADate() 和 static DateTime FromOADate(double) 兩個函數來解決這個問題前者將當前對象按原來的 double 值輸出後者則從一個 double 值獲得一個 SystemDateTime 對象舉例如下
private void TestDateTimeLong() {
double doubleDate = DateTimeNowToOADate();
DateTime theDate = DateTimeFromOADate(doubleDate);
thistextBoxText = ;
thistextBoxAppendText(Double value of now: + doubleDateToString() + \n);
thistextBoxAppendText(DateTime from double value: + theDateToString() + \n);
}
運行結果
Double value of now:
DateTime from double value: ::
格式化日期型數據
編程的過程中通常需要將日期型數據按照一定的格式輸出當然輸出結果肯定是字符串為此我們需要使用 SystemDateTime 類的 ToString() 方法並為其指定格式字符串MSDN 中SystemGlobalizationDateTimeFormatInfo 類的概述裡對模式字符串有非常詳細的說明因此這裡我只對常用的一些格式進行說明首先請看下表
d
月中的某一天
一位數的日期沒有前導零
dd
月中的某一天
一位數的日期有一個前導零
ddd
周中某天的縮寫名稱
在 AbbreviatedDayNames 中定義
dddd
周中某天的完整名稱
在 DayNames 中定義
M
月份數字
一位數的月份沒有前導零
MM
月份數字
一位數的月份有一個前導零
MMM
月份的縮寫名稱
在 AbbreviatedMonthNames 中定義
MMMM
月份的完整名稱
在 MonthNames 中定義
y
不包含紀元的年份
如果不包含紀元的年份小於 則顯示不具有前導零的年份
yy
不包含紀元的年份
如果不包含紀元的年份小於 則顯示具有前導零的年份
yyyy
包括紀元的四位數的年份
h
小時制的小時
一位數的小時數沒有前導零
hh
小時制的小時
一位數的小時數有前導零
H
小時制的小時
一位數的小時數沒有前導零
HH
小時制的小時
一位數的小時數有前導零
m
分鐘
一位數的分鐘數沒有前導零
mm
分鐘
一位數的分鐘數有一個前導零
s
秒
一位數的秒數沒有前導零
ss
秒
一位數的秒數有一個前導零
為了便於大家的理解不妨試試下面的程序
private void TestDateTimeToString() {
DateTime now = DateTimeNow;
string format;
thistextBoxText = ;
format = yyyyMMdd HH:mm:ss;
thistextBoxAppendText(format + : + nowToString(format) + \n);
format = yy年M日d日;
thistextBoxAppendText(format + : + nowToString(format) + \n);
}
這段程序將輸出結果
yyyyMMdd HH:mm:ss: ::
yy年M日d日: 年日日
這時候又出現一個問題如果要輸出的文本信息中包含格式字符怎麼辦?如
format = year: yyyy month: MM day: dd;
thistextBoxAppendText(nowToString(format) + \n);
將輸出
ear: on下: a:
這並不是我想要的結果怎麼辦呢?有辦法——
format = \year\: yyyy \month\: MM \day\: dd;
thistextBoxAppendText(nowToString(format) + \n);
看這次運行結果對了
year: month: day:
可以看出只需要使用單引號或者雙引號將文本信息括起來就好
From:http://tw.wingwit.com/Article/program/net/201311/12544.html