1.
装箱、拆箱
还
是
别
名
许
多
C#.NET
的
书
上都有介
绍
int -> Int32
是一个装箱的
过
程,反之
则
是拆箱的
过
程。
许
多其它
变
量
类
型也是如此,如:
short <-> Int16
,
long <-> Int64
等。
对
于一般的程序
员
来
说
,大可不必去了解
这
一
过
程,因
为这
些装箱和拆箱的
动
作都是可以自
动
完成的,不需要写代
码进
行干
预
。但是我
们
需要
记
住
这
些
类
型之
间
的
关
系,所以,我
们
使用
“
别
名
”
来
记忆
它
们
之
间
的
关
系。
C# 是全面向 对 象的 语 言,比 Java 的面向 对 象都 还彻 底 —— 它把 简单 数据 类 型通 过 默 认 的装箱 动 作封装成了 类 。 Int32 、 Int16 、 Int64 等就是相 应 的 类 名,而那些我 们 熟悉的、 简单 易 记 的名称,如 int 、 short 、 long 等,我 们 就可以把它称作是 Int32 、 Int16 、 Int64 等 类 型的 别 名。
那 么 除了 这 三 种类 型之外, 还 有哪些 类 有 “ 别 名 ” 呢?常用的有如下一些:
C# 是全面向 对 象的 语 言,比 Java 的面向 对 象都 还彻 底 —— 它把 简单 数据 类 型通 过 默 认 的装箱 动 作封装成了 类 。 Int32 、 Int16 、 Int64 等就是相 应 的 类 名,而那些我 们 熟悉的、 简单 易 记 的名称,如 int 、 short 、 long 等,我 们 就可以把它称作是 Int32 、 Int16 、 Int64 等 类 型的 别 名。
那 么 除了 这 三 种类 型之外, 还 有哪些 类 有 “ 别 名 ” 呢?常用的有如下一些:
bool -> System.Boolean (
布
尔
型,其
值为
true
或者 false)
char -> System.Char (字符型,占有两个字 节 ,表示 1 个 Unicode 字符)
byte -> System.Byte (字 节 型,占 1 字 节 ,表示 8 位正整数,范 围 0 ~ 255)
sbyte -> System.SByte ( 带 符号字 节 型,占 1 字 节 ,表示 8 位整数,范 围 -128 ~ 127)
ushort -> System.UInt16 ( 无符号短整型,占 2 字 节 ,表示 16 位正整数,范 围 0 ~ 65,535)
uint -> System.UInt32 ( 无符号整型,占 4 字 节 ,表示 32 位正整数,范 围 0 ~ 4,294,967,295)
ulong -> System.UInt64 ( 无符号 长 整型,占 8 字 节 ,表示 64 位正整数,范 围 0 ~ 大 约 10 的 20 次方)
short -> System.Int16 (短整型,占 2 字 节 ,表示 16 位整数,范 围 -32,768 ~ 32,767)
int -> System.Int32 ( 整型,占 4 字 节 ,表示 32 位整数,范 围 -2,147,483,648 到 2,147,483,647)
long -> System.Int64 ( 长 整型,占 8 字 节 ,表示 64 位整数,范 围 大 约 -(10 的 19) 次方 到 10 的 19 次方)
float -> System.Single ( 单 精度浮点型,占 4 个字 节 )
double -> System.Double ( 双精度浮点型,占 8 个字 节 )
char -> System.Char (字符型,占有两个字 节 ,表示 1 个 Unicode 字符)
byte -> System.Byte (字 节 型,占 1 字 节 ,表示 8 位正整数,范 围 0 ~ 255)
sbyte -> System.SByte ( 带 符号字 节 型,占 1 字 节 ,表示 8 位整数,范 围 -128 ~ 127)
ushort -> System.UInt16 ( 无符号短整型,占 2 字 节 ,表示 16 位正整数,范 围 0 ~ 65,535)
uint -> System.UInt32 ( 无符号整型,占 4 字 节 ,表示 32 位正整数,范 围 0 ~ 4,294,967,295)
ulong -> System.UInt64 ( 无符号 长 整型,占 8 字 节 ,表示 64 位正整数,范 围 0 ~ 大 约 10 的 20 次方)
short -> System.Int16 (短整型,占 2 字 节 ,表示 16 位整数,范 围 -32,768 ~ 32,767)
int -> System.Int32 ( 整型,占 4 字 节 ,表示 32 位整数,范 围 -2,147,483,648 到 2,147,483,647)
long -> System.Int64 ( 长 整型,占 8 字 节 ,表示 64 位整数,范 围 大 约 -(10 的 19) 次方 到 10 的 19 次方)
float -> System.Single ( 单 精度浮点型,占 4 个字 节 )
double -> System.Double ( 双精度浮点型,占 8 个字 节 )
我
们
可以用下列代
码
做一个
实验
:
private void TestAlias()
{
// this.textBox1 是一个文本框, 类 型 为 System.Windows.Forms.TextBox
// 设计 中已 经 将其 Multiline 属性 设 置 为 true
byte a = 1;
char b = 'a';
short c = 1;
int d = 2;
long e = 3;
uint f = 4;
bool g = true;
this.textBox1.Text = "";
this.textBox1.AppendText("byte -> " + a.GetType().FullName + "/n");
this.textBox1.AppendText("char -> " + b.GetType().FullName + "/n");
this.textBox1.AppendText("short -> " + c.GetType().FullName + "/n");
this.textBox1.AppendText("int -> " + d.GetType().FullName + "/n");
this.textBox1.AppendText("long -> " + e.GetType().FullName + "/n");
this.textBox1.AppendText("uint -> " + f.GetType().FullName + "/n");
this.textBox1.AppendText("bool -> " + g.GetType().FullName + "/n");
}
{
// this.textBox1 是一个文本框, 类 型 为 System.Windows.Forms.TextBox
// 设计 中已 经 将其 Multiline 属性 设 置 为 true
byte a = 1;
char b = 'a';
short c = 1;
int d = 2;
long e = 3;
uint f = 4;
bool g = true;
this.textBox1.Text = "";
this.textBox1.AppendText("byte -> " + a.GetType().FullName + "/n");
this.textBox1.AppendText("char -> " + b.GetType().FullName + "/n");
this.textBox1.AppendText("short -> " + c.GetType().FullName + "/n");
this.textBox1.AppendText("int -> " + d.GetType().FullName + "/n");
this.textBox1.AppendText("long -> " + e.GetType().FullName + "/n");
this.textBox1.AppendText("uint -> " + f.GetType().FullName + "/n");
this.textBox1.AppendText("bool -> " + g.GetType().FullName + "/n");
}
在窗体中新建一个按
钮
,并在它的
单击
事件中
调
用
该
TestAlias()
函数,我
们
将看到运行
结
果如下:
byte -> System.Byte
char -> System.Char
short -> System.Int16
int -> System.Int32
long -> System.Int64
uint -> System.UInt32
bool -> System.Boolean
char -> System.Char
short -> System.Int16
int -> System.Int32
long -> System.Int64
uint -> System.UInt32
bool -> System.Boolean
这
足以
说
明各
别
名
对应
的
类
!
2.
数
值类
型之
间
的相互
转换
这
里所
说
的数
值类
型包括 byte, short, int, long, fload, double 等,根据
这
个排列
顺
序,各
种类
型的
值
依次可以向后自
动进
行
转换
。
举
个例来
说
,把一个 short 型的数据
赋值给
一个 int 型的
变
量,short
值
会自
动
行
转换
成 int 型
值
,再
赋给
int
型
变
量。如下例:
private void TestBasic()
{
byte a = 1;
short b = a;
int c = b;
long d = c;
float e = d;
double f = e;
this.textBox1.Text = "";
this.textBox1.AppendText("byte a = " + a.ToString() + "/n");
this.textBox1.AppendText("short b = " + b.ToString() + "/n");
this.textBox1.AppendText("int c = " + c.ToString() + "/n");
this.textBox1.AppendText("long d = " + d.ToString() + "/n");
this.textBox1.AppendText("float e = " + e.ToString() + "/n");
this.textBox1.AppendText("double f = " + f.ToString() + "/n");
}
{
byte a = 1;
short b = a;
int c = b;
long d = c;
float e = d;
double f = e;
this.textBox1.Text = "";
this.textBox1.AppendText("byte a = " + a.ToString() + "/n");
this.textBox1.AppendText("short b = " + b.ToString() + "/n");
this.textBox1.AppendText("int c = " + c.ToString() + "/n");
this.textBox1.AppendText("long d = " + d.ToString() + "/n");
this.textBox1.AppendText("float e = " + e.ToString() + "/n");
this.textBox1.AppendText("double f = " + f.ToString() + "/n");
}
译顺
利通
过
,运行
结
果是各
变
量的
值
均
为
1
;当然,它
们
的
类
型分
别还
是
System.Byte
型
……System.Double
型。
现
在我
们
来
试试
,如果把
赋值
的
顺
序反
过
来会怎
么样
呢?在
TestBasic()
函数中追加如下
语
句:
int g = 1;
short h = g;
this.textBox1.AppendText("h = " + h.ToString() + "/n");
short h = g;
this.textBox1.AppendText("h = " + h.ToString() + "/n");
结
果
编译报错
:
G:/Projects/Visual C#/Convert/Form1.cs(118): 无法将 类 型“int” 隐 式 转换为 “short”
其中,Form1.cs 的 118 行即 short h = g 所在行。
G:/Projects/Visual C#/Convert/Form1.cs(118): 无法将 类 型“int” 隐 式 转换为 “short”
其中,Form1.cs 的 118 行即 short h = g 所在行。
这
个
时
候,如果我
们坚
持要
进
行
转换
,就
应该
使用
强
制
类
型
转换
,
这
在
C
语
言中常有提及,就是使用
“(
类
型名
)
变
量名
”
形式的
语
句来
对
数据
进
行
强
制
转换
。如上例修改如下:
short g = 1;
byte h = (byte) g; // 将 short 型的 g 的 值强 制 转换 成 short 型后再 赋给变 量 h
this.textBox1.AppendText("h = " + h.ToString() + "/n");
byte h = (byte) g; // 将 short 型的 g 的 值强 制 转换 成 short 型后再 赋给变 量 h
this.textBox1.AppendText("h = " + h.ToString() + "/n");
编译
通
过
,运行
结
果
输
出了
h = 1
,
转换
成功。
但是,如果我 们 使用 强 制 转换 ,就不得不再考 虑 一个 问题 : short 型的范 围 是 -32768 ~ 23767 ,而 byte 型的范 围 是 0 ~ 255 ,那 么 ,如果 变 量 g 的大小超 过 了 byte 型的范 围 又会出 现 什 么样 的情况呢?我 们 不妨再一次改写代 码 ,将 值 改 为 265 ,比 255 大 10
但是,如果我 们 使用 强 制 转换 ,就不得不再考 虑 一个 问题 : short 型的范 围 是 -32768 ~ 23767 ,而 byte 型的范 围 是 0 ~ 255 ,那 么 ,如果 变 量 g 的大小超 过 了 byte 型的范 围 又会出 现 什 么样 的情况呢?我 们 不妨再一次改写代 码 ,将 值 改 为 265 ,比 255 大 10
short g = 265; //265 = 255 + 10
byte h = (byte) g;
this.textBox1.AppendText("h = " + h.ToString() + "/n");
byte h = (byte) g;
this.textBox1.AppendText("h = " + h.ToString() + "/n");
编译
没有出
错
,运行
结
果却不是
h = 265
,而是
h = 9
。
因此,我 们 在 进 行 转换 的 时 候, 应 当注意被 转换 的数据不能超出目 标类 型的范 围 。 这 不 仅 体 现 在多字 节 数据 类 型 ( 相 对 ,如上例的 short) 转换为 少字 节类 型 ( 相 对 ,如上例的 byte) 时 ,也体 现 在字 节 数相同的有符号 类 型和无符号 类 型之 间 ,如将 byte 的 129 转换为 sbyte 就会溢出。 这 方面的例子大同小异,就不 详细说 明了。
因此,我 们 在 进 行 转换 的 时 候, 应 当注意被 转换 的数据不能超出目 标类 型的范 围 。 这 不 仅 体 现 在多字 节 数据 类 型 ( 相 对 ,如上例的 short) 转换为 少字 节类 型 ( 相 对 ,如上例的 byte) 时 ,也体 现 在字 节 数相同的有符号 类 型和无符号 类 型之 间 ,如将 byte 的 129 转换为 sbyte 就会溢出。 这 方面的例子大同小异,就不 详细说 明了。
3.
字符的
ASCII
码
和
Unicode
码
很多
时
候我
们
需要得到一个英文字符的
ASCII
码
,或者一个
汉
字字符的
Unicode
码
,或者从相
关
的
编码查询
它是哪一个字符的
编码
。很多人,尤其是从
VB
程序序
转过
来学
C#
的人,会
报
怨
C#
里
为
什
么
没有提供
现
成的函数来做
这
个事情
——
因
为
在
VB
中有
Asc()
函数和
Chr()
函数用于
这类转换
。
但是如果你学 过 C ,你就会清楚,我 们 只需要将英文字符型数据 强 制 转换 成合适的数 值 型数据,就可以得到相 应 的 ASCII 码 ;反之,如果将一个合适的数 值 型数据 强 制 转换 成字符型数据,就可以得到相 应 的字符。
C# 中字符的范 围扩 大了,不 仅 包含了 单 字 节 字符,也可以包含双字 节 字符,如中文字符等。而在字符和 编码 之 间 的 转换 , 则 仍延用了 C 语 言的做法 —— 强 制 转换 。 不妨看看下面的例子
但是如果你学 过 C ,你就会清楚,我 们 只需要将英文字符型数据 强 制 转换 成合适的数 值 型数据,就可以得到相 应 的 ASCII 码 ;反之,如果将一个合适的数 值 型数据 强 制 转换 成字符型数据,就可以得到相 应 的字符。
C# 中字符的范 围扩 大了,不 仅 包含了 单 字 节 字符,也可以包含双字 节 字符,如中文字符等。而在字符和 编码 之 间 的 转换 , 则 仍延用了 C 语 言的做法 —— 强 制 转换 。 不妨看看下面的例子
private void TestChar()
{
char ch = 'a';
short ii = 65; < BR > this.textBox1.Text = "";
this.textBox1.AppendText("The ASCII code of /'" + ch + "/' is: " + (short) ch + "/n");
this.textBox1.AppendText("ASCII is " + ii.ToString() + ", the char is: " + (char) ii + "/n");
char cn = ' 中';
short uc = 22478;
this.textBox1.AppendText("The Unicode of /'" + cn + "/' is: " + (short) cn + "/n");
this.textBox1.AppendText("Unicode is " + uc.ToString() + ", the char is: " + (char) uc + "/n");
}
{
char ch = 'a';
short ii = 65; < BR > this.textBox1.Text = "";
this.textBox1.AppendText("The ASCII code of /'" + ch + "/' is: " + (short) ch + "/n");
this.textBox1.AppendText("ASCII is " + ii.ToString() + ", the char is: " + (char) ii + "/n");
char cn = ' 中';
short uc = 22478;
this.textBox1.AppendText("The Unicode of /'" + cn + "/' is: " + (short) cn + "/n");
this.textBox1.AppendText("Unicode is " + uc.ToString() + ", the char is: " + (char) uc + "/n");
}
它的运行
结
果是
The ASCII code of 'a' is: 97
ASCII is 65, the char is: A
The Unicode of ' 中' is: 20013
Unicode is 22478, the char is: 城
ASCII is 65, the char is: A
The Unicode of ' 中' is: 20013
Unicode is 22478, the char is: 城
从
这
个例子中,我
们
便能非常清楚的了解
——
通
过强
制
转换
,可以得以字符的
编码
,或者得到
编码
表示的字符。如果你需要的不是
short
型的
编码
,
请
参考第
1
条
进
行
转换
,即可得到
int
等
类
型的
编码值
。
4.
数
值
字符串和数
值
之
间
的
转换
首先,我
们
得搞明白,什
么
是数
值
字符串。我
们
知道,在
C#
中,字符串是用一
对
双引号包含的若干字符来表示的,如
"123"
。而
"123"
又相
对
特殊,因
为组
成
该
字符串的字符都是数字,
这样
的字符串,就是数
值
字符串。在我
们
的眼中,
这
即是一串字符,也是一个数,但
计
算机却只
认为
它是一个字符串,不是数。因此,我
们
在某些
时
候,比如
输
入数
值
的
时
候,把字符串
转换
成数
值
;而在另一些
时
候,我
们
需要相反的
转换
。
将数 值转换 成字符串非常 简单 ,因 为每 一个 类 都有一个 void ToString() 方法。所有数 值 型的 void ToString() 方法都能将数据 转换为 数 值 字符串。如 123.ToSting() 就将得到字符串 "123" 。
那 么 反 过 来,将数 值 型字符串 转换 成数 值 又 该 怎 么办 呢?我 们 仔 细查 找一下,会 发现 short, int, float 等数 值类 型均有一个 static Parse() 函数。 这 个函数就是用来将字符串 转换为 相 应 数 值 的。我 们 以一个 float 类 型的 转换为 例: float f = float.Parse("543.21"); 其 结 果 f 的 值为 543.21F 。当然,其它的数 值类 型也可以使用同 样 的方法 进 行 转换 ,下面的例子可以更明确的 说 明 转换 的方法:
将数 值转换 成字符串非常 简单 ,因 为每 一个 类 都有一个 void ToString() 方法。所有数 值 型的 void ToString() 方法都能将数据 转换为 数 值 字符串。如 123.ToSting() 就将得到字符串 "123" 。
那 么 反 过 来,将数 值 型字符串 转换 成数 值 又 该 怎 么办 呢?我 们 仔 细查 找一下,会 发现 short, int, float 等数 值类 型均有一个 static Parse() 函数。 这 个函数就是用来将字符串 转换为 相 应 数 值 的。我 们 以一个 float 类 型的 转换为 例: float f = float.Parse("543.21"); 其 结 果 f 的 值为 543.21F 。当然,其它的数 值类 型也可以使用同 样 的方法 进 行 转换 ,下面的例子可以更明确的 说 明 转换 的方法:
private void TestStringValue()
{
float f = 54.321F;
string str = "123";
this.textBox1.Text = "";
this.textBox1.AppendText("f = " + f.ToString() + "/n");
if (int.Parse(str) == 123)
{
this.textBox1.AppendText("str convert to int successfully.");
}
else
{
this.textBox1.AppendText("str convert to int failed.");
}
}
{
float f = 54.321F;
string str = "123";
this.textBox1.Text = "";
this.textBox1.AppendText("f = " + f.ToString() + "/n");
if (int.Parse(str) == 123)
{
this.textBox1.AppendText("str convert to int successfully.");
}
else
{
this.textBox1.AppendText("str convert to int failed.");
}
}
运行
结
果:
f = 54.321
str convert to int successfully.
str convert to int successfully.
5.
字符串和字符数
组
之
间
的
转换
字符串
类
System.String
提供了一个 void ToCharArray() 方法,
该
方法可以
实现
字符串到字符数
组
的
转换
。如下例:
private void TestStringChars()
{
string str = "mytest";
char[] chars = str.ToCharArray();< BR > this.textBox1.Text = "";
this.textBox1.AppendText("Length of /"mytest/" is " + str.Length + "/n");
this.textBox1.AppendText("Length of char array is " + chars.Length + "/n");
this.textBox1.AppendText("char[2] = " + chars[2] + "/n"); }
{
string str = "mytest";
char[] chars = str.ToCharArray();< BR > this.textBox1.Text = "";
this.textBox1.AppendText("Length of /"mytest/" is " + str.Length + "/n");
this.textBox1.AppendText("Length of char array is " + chars.Length + "/n");
this.textBox1.AppendText("char[2] = " + chars[2] + "/n"); }
例中以
对转换转换
到的字符数
组长
度和它的一个元素
进
行了
测试
,
结
果如下:
Length of "mytest" is 6
Length of char array is 6
char[2] = t
Length of char array is 6
char[2] = t
可以看出,
结
果完全正确,
这说
明
转换
成功。那
么
反
过
来,要把字符数
组转换
成字符串又
该
如何呢?
我 们 可以使用 System.String 类 的构造函数来解决 这 个 问题 。 System.String 类 有两个构造函数是通 过 字符数 组 来构造的,即 String(char[]) 和 String[char[], int, int) 。后者之所以多两个参数,是因 为 可以指定用字符数 组 中的哪一部分来构造字符串。而前者 则 是用字符数 组 的全部元素来构造字符串。我 们 以前者 为 例,在 TestStringChars() 函数中 输 入如下 语 句:
我 们 可以使用 System.String 类 的构造函数来解决 这 个 问题 。 System.String 类 有两个构造函数是通 过 字符数 组 来构造的,即 String(char[]) 和 String[char[], int, int) 。后者之所以多两个参数,是因 为 可以指定用字符数 组 中的哪一部分来构造字符串。而前者 则 是用字符数 组 的全部元素来构造字符串。我 们 以前者 为 例,在 TestStringChars() 函数中 输 入如下 语 句:
char[] tcs = {'t', 'e', 's', 't', ' ', 'm', 'e'};
string tstr = new String(tcs);
this.textBox1.AppendText("tstr = /"" + tstr + "/"/n");
string tstr = new String(tcs);
this.textBox1.AppendText("tstr = /"" + tstr + "/"/n");
运行
结
果
输
入
tstr = "test me"
,
测试说
明
转换
成功。
实际 上,我 们 在很多 时 候需要把字符串 转换 成字符数 组 只是 为 了得到 该 字符串中的某个字符。如果只是 为 了 这 个目的,那大可不必 兴师动 众的去 进 行 转换 ,我 们 只需要使用 System.String 的 [] 运算符就可以达到目的。 请 看下例,再在 TestStringChars() 函数中加入如如下 语 名:
实际 上,我 们 在很多 时 候需要把字符串 转换 成字符数 组 只是 为 了得到 该 字符串中的某个字符。如果只是 为 了 这 个目的,那大可不必 兴师动 众的去 进 行 转换 ,我 们 只需要使用 System.String 的 [] 运算符就可以达到目的。 请 看下例,再在 TestStringChars() 函数中加入如如下 语 名:
char ch = tstr[3];
this.textBox1.AppendText("/"" + tstr + "/"[3] = " + ch.ToString());
this.textBox1.AppendText("/"" + tstr + "/"[3] = " + ch.ToString());
正确的
输
出是
"test me"[3] = t
,
经测试
,
输
出正确。
6.
字符串和字
节
数
组
之
间
的
转换
如果
还
想从
System.String
类
中找到方法
进
行字符串和字
节
数
组
之
间
的
转换
,恐怕你会失望了。
为
了
进
行
这样
的
转换
,我
们
不得不借助另一个
类
:
System.Text.Encoding
。
该类
提供了
bye[] GetBytes(string)
方法将字符串
转换
成字
节
数
组
,
还
提供了
string GetString(byte[])
方法将字
节
数
组转换
成字符串。
System.Text.Encoding 类 似乎没有可用的构造函数,但我 们 可以找到几个默 认 的 Encoding,即 Encoding.Default( 获 取系 统 的当前 ANSI 代 码页 的 编码 ) 、Encoding.ASCII( 获 取 7 位 ASCII 字符集的 编码 ) 、Encoding.Unicode( 获 取采用 Little-Endian 字 节顺 序的 Unicode 格式的 编码 ) 、Encoding.UTF7( 获 取 UTF-7 格式的 编码 ) 、Encoding.UTF8( 获 取 UTF-8 格式的 编码 ) 等。 这 里主要 说说 Encoding.Default 和 Encoding.Unicode 用于 转换 的区 别 。
在字符串 转换 到字 节 数 组 的 过 程中, Encoding.Default 会将 每 个 单 字 节 字符,如半角英文, 转换 成 1 个字 节 ,而把 每 个双字 节 字符,如 汉 字, 转换 成 2 个字 节 。而 Encoding.Unicode 则 会将它 们 都 转换 成两个字 节 。我 们 可以通 过 下列 简单 的了解一下 转换 的方法,以及使用 Encoding.Default 和 Encodeing.Unicode 的区 别 :
System.Text.Encoding 类 似乎没有可用的构造函数,但我 们 可以找到几个默 认 的 Encoding,即 Encoding.Default( 获 取系 统 的当前 ANSI 代 码页 的 编码 ) 、Encoding.ASCII( 获 取 7 位 ASCII 字符集的 编码 ) 、Encoding.Unicode( 获 取采用 Little-Endian 字 节顺 序的 Unicode 格式的 编码 ) 、Encoding.UTF7( 获 取 UTF-7 格式的 编码 ) 、Encoding.UTF8( 获 取 UTF-8 格式的 编码 ) 等。 这 里主要 说说 Encoding.Default 和 Encoding.Unicode 用于 转换 的区 别 。
在字符串 转换 到字 节 数 组 的 过 程中, Encoding.Default 会将 每 个 单 字 节 字符,如半角英文, 转换 成 1 个字 节 ,而把 每 个双字 节 字符,如 汉 字, 转换 成 2 个字 节 。而 Encoding.Unicode 则 会将它 们 都 转换 成两个字 节 。我 们 可以通 过 下列 简单 的了解一下 转换 的方法,以及使用 Encoding.Default 和 Encodeing.Unicode 的区 别 :
private void TestStringBytes()
{
string s = "C# 语 言 ";
byte[] b1 = System.Text.Encoding.Default.GetBytes(s);
byte[] b2 = System.Text.Encoding.Unicode.GetBytes(s);
string t1 = "", t2 = "";
foreach (byte b in b1) { t1 += b.ToString("") + " "; }
foreach (byte b in b2) { t2 += b.ToString("") + " "; }
this.textBox1.Text = "";
this.textBox1.AppendText("b1.Length = " + b1.Length + "/n");
this.textBox1.AppendText(t1 + "/n");
this.textBox1.AppendText("b2.Length = " + b2.Length + "/n");
this.textBox1.AppendText(t2 + "/n"); }
{
string s = "C# 语 言 ";
byte[] b1 = System.Text.Encoding.Default.GetBytes(s);
byte[] b2 = System.Text.Encoding.Unicode.GetBytes(s);
string t1 = "", t2 = "";
foreach (byte b in b1) { t1 += b.ToString("") + " "; }
foreach (byte b in b2) { t2 += b.ToString("") + " "; }
this.textBox1.Text = "";
this.textBox1.AppendText("b1.Length = " + b1.Length + "/n");
this.textBox1.AppendText(t1 + "/n");
this.textBox1.AppendText("b2.Length = " + b2.Length + "/n");
this.textBox1.AppendText(t2 + "/n"); }
运行
结
果如下,不
说详
述,相信大家已
经
明白了。
b1.Length = 6
67 35 211 239 209 212
b2.Length = 8
67 0 35 0 237 139 0 138
67 35 211 239 209 212
b2.Length = 8
67 0 35 0 237 139 0 138
将字
节
数
组转换
成字符串,使用 Encoding
类
的 string GetString(byte[]) 或 string GetString(byte[], int, int) 方法,具体使用何
种
Encoding
还
是由
编码
决定。在 TestStringBytes() 函数中添加如下
语
句作
为实
例:
byte[] bs = {97, 98, 99, 100, 101, 102};
string ss = System.Text.Encoding.ASCII.GetString(bs);
this.textBox1.AppendText("The string is: " + ss + "/n");
string ss = System.Text.Encoding.ASCII.GetString(bs);
this.textBox1.AppendText("The string is: " + ss + "/n");
运行
结
果
为
:
The string is: abcdef
7.
各
种
数
值类
型和字
节
数
组
之
间
的
转换
在第
1
条中我
们
可以
查
到各
种
数
值
型需要使用多少字
节
的空
间
来保存数据。将某
种
数
值类
型的数据
转换
成字
节
数
组
的
时
候,得到的一定是相
应
大小的字
节
数
组
;同
样
,需要把字
节
数
组转换
成数
值类
型,也需要
这
个字
节
数
组
大于相
应
数
值类
型的字
节
数。
现 在介 绍 此 类转换 的主角:System.BitConverter。 该类 提供了 byte[] GetBytes(...) 方法将各 种 数 值类 型 转换 成字 节 数 组 ,也提供了 ToInt32、ToInt16、ToInt64、ToUInt32、ToSignle、ToBoolean 等方法将字 节 数 组转换 成相 应 的数 值类 型。
现 在介 绍 此 类转换 的主角:System.BitConverter。 该类 提供了 byte[] GetBytes(...) 方法将各 种 数 值类 型 转换 成字 节 数 组 ,也提供了 ToInt32、ToInt16、ToInt64、ToUInt32、ToSignle、ToBoolean 等方法将字 节 数 组转换 成相 应 的数 值类 型。
由于
这类转换
通常只是在需要
进
行
较细
微的
编码
/
解
码
操作
时
才会用到,所以
这
里就不
详细
叙述了,
仅
把
System.BitConverter
类
介
绍给
大家。
8.
转换
成十六
进
制
任何数据在
计
算机内部都是以二
进
制保存的,所以
进
制与数据的存
储
无
关
,只与
输
入
输
出有
关
。所以,
对
于
进
制
转换
,我
们
只
关
心字符串中的
结
果。
在上面的第 4 条中提到了 ToString() 方法可以将数 值转换 成字符串,不 过 在字符串中, 结 果是以十 进 制 显 示的。 现 在我 们带给 它加一些参数,就可以将其 转换 成十六 进 制 —— 使用 ToString(string) 方法。
这 里需要一个 string 类 型的参数, 这 就是格式 说 明符。十六 进 制的格式 说 明符是 "x" 或者 "X" ,使用 这 两 种 格式 说 明符的区 别 主要在于 A-F 六个数字: "x" 代表 a-f 使用小写字母表示,而 "X" 而表示 A-F 使用大字字母表示。 如下例:
在上面的第 4 条中提到了 ToString() 方法可以将数 值转换 成字符串,不 过 在字符串中, 结 果是以十 进 制 显 示的。 现 在我 们带给 它加一些参数,就可以将其 转换 成十六 进 制 —— 使用 ToString(string) 方法。
这 里需要一个 string 类 型的参数, 这 就是格式 说 明符。十六 进 制的格式 说 明符是 "x" 或者 "X" ,使用 这 两 种 格式 说 明符的区 别 主要在于 A-F 六个数字: "x" 代表 a-f 使用小写字母表示,而 "X" 而表示 A-F 使用大字字母表示。 如下例:
private void TestHex()
{
int a = 188;
this.textBox1.Text = "";
this.textBox1.AppendText("a(10) = " + a.ToString() + "/n");
this.textBox1.AppendText("a(16) = " + a.ToString("x") + "/n");
this.textBox1.AppendText("a(16) = " + a.ToString("X") + "/n"); }
{
int a = 188;
this.textBox1.Text = "";
this.textBox1.AppendText("a(10) = " + a.ToString() + "/n");
this.textBox1.AppendText("a(16) = " + a.ToString("x") + "/n");
this.textBox1.AppendText("a(16) = " + a.ToString("X") + "/n"); }
运行
结
果如下:
a(10) = 188
a(16) = bc
a(16) = BC
a(16) = bc
a(16) = BC
这时
候,我
们
可能有另一
种
需求,即
为
了
显
示
结
果的整
齐
,我
们
需要控制十六
进
制表示的
长
度,如果
长
度不
够
,用前
导
的
0
填
补
。解决
这
个
问题
,我
们
只需要在格式
说
明符
“x”
或者
“X”
后写上表示
长
度的数字就行了。比如,要限制在
4
个字符的
长
度,可以写成
“X4”
。
在上例中追加一句:
this.textBox1.AppendText("a(16) = " + a.ToString("X4") + "/n");
其
结
果将
输
出
a(16) = 00BC
。
现 在,我 们还 要 说 一 说 如何将一个表示十六 进 制数的字符串 转换 成整型。 这 一 转换 ,同 样 需要借助于 Parse() 方法。 这 里,我需要 Parse(string, System.Globalization.NumberStyles) 方法。第一个参数是表示十六 进 制数的字符串,如 “AB” 、 “20”( 表示十 进 制的 32) 等。第二个参数 System.Globalization.NumberStyles 是一个枚 举类 型,用来表示十六 进 制的枚 举值 是 HexNumber 。因此,如果我 们 要将 “AB” 转换 成整型,就 应该这样 写: int b = int.Parse("AB", System.Globalization.NumberStyles.HexNumber) ,最后得到的 b 的 值 是 171 。
现 在,我 们还 要 说 一 说 如何将一个表示十六 进 制数的字符串 转换 成整型。 这 一 转换 ,同 样 需要借助于 Parse() 方法。 这 里,我需要 Parse(string, System.Globalization.NumberStyles) 方法。第一个参数是表示十六 进 制数的字符串,如 “AB” 、 “20”( 表示十 进 制的 32) 等。第二个参数 System.Globalization.NumberStyles 是一个枚 举类 型,用来表示十六 进 制的枚 举值 是 HexNumber 。因此,如果我 们 要将 “AB” 转换 成整型,就 应该这样 写: int b = int.Parse("AB", System.Globalization.NumberStyles.HexNumber) ,最后得到的 b 的 值 是 171 。
9.
日期型数据和
长
整型数据之
间
的
转换
为
什
么
要将日期型数据
转换为长
整型数据呢?原因很多,但就我个人来
说
,
经
常将它用于数据
库
的日期存
储
。由于各
种
数据
库对
日期型的定
义
和
处
理是不一
样
的,各
种语
言
对
日期型数据的定
义
的
处
理也各不相同,因
为
,我宁愿将日期型数据
转换
成
长
整型再保存到数据
库
中。
虽
然也可以使用字符串来保存,但使用字符串也会
涉
及到
许
多
问题
,如区域等
问题
,而且,它需要比保存
长
整型数据更多的空
间
。
日期型数据,在 C# 中的参与运算的 时 候, 应该 也是 转换为长 整型数据来运算的。它的 长 整型 值 是自 0001 年 1 月 1 日午夜 12:00 以来所 经过时间 以 100 毫微秒 为间 隔表示 时 的数字。 这 个数在 C# 的 DateTime 中被称 为 Ticks( 刻度 ) 。 DateTime 类 型有一个名 为 Ticks 的 长 整型只 读 属性,就保存着 这 个 值 。如此,要从一个 DataTime 型数据得到 long 型 值 就非常 简单 了,只需要 读 出 DataTime 对 象的 Ticks 值 即可,如:
日期型数据,在 C# 中的参与运算的 时 候, 应该 也是 转换为长 整型数据来运算的。它的 长 整型 值 是自 0001 年 1 月 1 日午夜 12:00 以来所 经过时间 以 100 毫微秒 为间 隔表示 时 的数字。 这 个数在 C# 的 DateTime 中被称 为 Ticks( 刻度 ) 。 DateTime 类 型有一个名 为 Ticks 的 长 整型只 读 属性,就保存着 这 个 值 。如此,要从一个 DataTime 型数据得到 long 型 值 就非常 简单 了,只需要 读 出 DataTime 对 象的 Ticks 值 即可,如:
long longDate = DateTime.Now.Ticks;
DateTime
的构造函数中也提供了相
应
的,从
长
整型数据构造 DateTime 型数据的函数:DateTime(long)。如:
DateTime theDate = new DateTime(longDate);
但
这样对
于很多
VB6
程序
员
来
说
,是
给
他
们
出了一道
难题
,因
为
VB6
中的日期型数据内部是以
Double
型表示的,将其
转换为长
整型后得到的
仅仅
是日期,而没有
时间
。如何
协调这
两
种
日期
类
型呢?
System.DateTime 提供了 double ToOADate() 和 static DateTime FromOADate(double) 两个函数来解决 这 个 问题 。前者将当前 对 象按原来的 double 值输 出,后者 则 从一个 double 值获 得一个 System.DateTime 对 象。 举 例如下:
System.DateTime 提供了 double ToOADate() 和 static DateTime FromOADate(double) 两个函数来解决 这 个 问题 。前者将当前 对 象按原来的 double 值输 出,后者 则 从一个 double 值获 得一个 System.DateTime 对 象。 举 例如下:
private void TestDateTimeLong()
{
double doubleDate = DateTime.Now.ToOADate();
DateTime theDate = DateTime.FromOADate(doubleDate); < BR > this.textBox1.Text = "";
this.textBox1.AppendText("Double value of now: " + doubleDate.ToString() + "/n");
this.textBox1.AppendText("DateTime from double value: " + theDate.ToString() + "/n"); }
{
double doubleDate = DateTime.Now.ToOADate();
DateTime theDate = DateTime.FromOADate(doubleDate); < BR > this.textBox1.Text = "";
this.textBox1.AppendText("Double value of now: " + doubleDate.ToString() + "/n");
this.textBox1.AppendText("DateTime from double value: " + theDate.ToString() + "/n"); }
运行
结
果:
Double value of now: 37494.661541713
DateTime from double value: 2002-8-26 15:52:37
DateTime from double value: 2002-8-26 15:52:37
10.
格式化日期型数据
编
程的
过
程中,通常需要将日期型数据按照一定的格式
输
出,当然,
输
出
结
果肯定是字符串。
为
此,我
们
需要使用
System.DateTime
类
的
ToString()
方法,并
为
其指定格式字符串。
MSDN 中,System.Globalization.DateTimeFormatInfo 类 的概述里 对 模式字符串有非常 详细 的 说 明,因此, 这 里我只 对 常用的一些格式 进 行 说 明,首先 请 看下表:
MSDN 中,System.Globalization.DateTimeFormatInfo 类 的概述里 对 模式字符串有非常 详细 的 说 明,因此, 这 里我只 对 常用的一些格式 进 行 说 明,首先 请 看下表:
d
|
月中的某一天
|
一位数的日期没有前
导
零
|
dd
|
月中的某一天
|
一位数的日期有一个前
导
零
|
ddd
|
周中某天的
缩
写名称
|
在 AbbreviatedDayNames 中定
义
|
dddd
|
周中某天的完整名称
|
在 DayNames 中定
义
|
M
|
月份数字
|
一位数的月份没有前
导
零
|
MM
|
月份数字
|
一位数的月份有一个前
导
零
|
MMM
|
月份的
缩
写名称
|
在 AbbreviatedMonthNames 中定
义
|
MMMM
|
月份的完整名称
|
在 MonthNames 中定
义
|
y
|
不包含
纪
元的年份
|
如果不包含
纪
元的年份小于
10
,
则显
示不具有前
导
零的年份
|
yy
|
不包含
纪
元的年份
|
如果不包含
纪
元的年份小于
10
,
则显
示具有前
导
零的年份
|
yyyy
|
包括
纪
元的四位数的年份
|
|
h
|
12
小
时
制的小
时
|
一位数的小
时
数没有前
导
零
|
hh
|
12
小
时
制的小
时
|
一位数的小
时
数有前
导
零
|
H
|
24
小
时
制的小
时
|
一位数的小
时
数没有前
导
零
|
HH
|
24
小
时
制的小
时
|
一位数的小
时
数有前
导
零
|
m
|
分
钟
|
一位数的分
钟
数没有前
导
零
|
mm
|
分
钟
|
一位数的分
钟
数有一个前
导
零
|
s
|
秒
|
一位数的秒数没有前
导
零
|
ss
|
秒
|
一位数的秒数有一个前
导
零
|
为
了便于大家的理解,不妨
试试
下面的程序:
private void TestDateTimeToString()
{
DateTime now = DateTime.Now;
string format;
this.textBox1.Text = "";
format = "yyyy-MM-dd HH:mm:ss";
this.textBox1.AppendText(format + ": " + now.ToString(format) + "/n");
format = "yy 年M日d日";
this.textBox1.AppendText(format + ": " + now.ToString(format) + "/n"); }
{
DateTime now = DateTime.Now;
string format;
this.textBox1.Text = "";
format = "yyyy-MM-dd HH:mm:ss";
this.textBox1.AppendText(format + ": " + now.ToString(format) + "/n");
format = "yy 年M日d日";
this.textBox1.AppendText(format + ": " + now.ToString(format) + "/n"); }
这
段程序将
输
出
结
果:
yyyy-MM-dd HH:mm:ss: 2002-08-26 17:03:04
yy 年 M 日 d 日 : 02 年 8 日 26 日
yy 年 M 日 d 日 : 02 年 8 日 26 日
这时
候,又出
现
一个
问题
,如果要
输
出的文本信息中包含格式字符怎
么办
?如
format = "year: yyyy, month: MM, day: dd";
this.textBox1.AppendText(now.ToString(format) + "/n");
this.textBox1.AppendText(now.ToString(format) + "/n");
将
输
出:
2ear: 2002, 4on
下5: 08, 26a2: 26
这
并不是我想要的
结
果,怎
么办
呢?有
办
法——
format = "/"year/": yyyy, /'month/': MM, /'day/': dd";
this.textBox1.AppendText(now.ToString(format) + "/n");
this.textBox1.AppendText(now.ToString(format) + "/n");
看,
这
次运行
结
果
对
了:
year: 2002, month: 08, day: 26