C#.NET 中的类型转换 作者:不详 来源于:不详 发布时间:2005-7-22 22:24:17 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
C# 出来也有些日子了,最近由于编程的需要,对 C# 的类型转换做了一些研究,其内容涉及 C# 的装箱/拆箱/别名、数值类型间相互转换、字符的 ASCII 码和 Unicode 码、数值字符串和数值之间的转换、字符串和字符数组/字节数组之间的转换、各种数值类型和字节数组之间的转换、十六进制数输出以及日期型数据的一些转换处理,在这里与大家分享—— 1. 装箱、拆箱还是别名 许多 C#.NET 的书上都有介绍 int -> Int32 是一个装箱的过程,反之则是拆箱的过程。许多其它变量类型也是如此,如:short <-> Int16,long <-> Int64 等。对于一般的程序员来说,大可不必去了解这一过程,因为这些装箱和拆箱的动作都是可以自动完成的,不需要写代码进行干预。但是我们需要记住这些类型之间的关系,所以,我们使用“别名”来记忆它们之间的关系。
我们可以用下列代码做一个实验: 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"); } 在窗体中新建一个按钮,并在它的单击事件中调用该 TestAlias() 函数,我们将看到运行结果如下:
这足以说明各别名对应的类! 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"); } 译顺利通过,运行结果是各变量的值均为 1;当然,它们的类型分别还是 System.Byte 型……System.Double 型。现在我们来试试,如果把赋值的顺序反过来会怎么样呢?在 TestBasic() 函数中追加如下语句:
结果编译报错: 这个时候,如果我们坚持要进行转换,就应该使用强制类型转换,这在 C 语言中常有提及,就是使用“(类型名) 变量名”形式的语句来对数据进行强制转换。如上例修改如下:
编译通过,运行结果输出了 h = 1,转换成功。
编译没有出错,运行结果却不是 h = 265,而是 h = 9。 3. 字符的 ASCII 码和 Unicode 码 很多时候我们需要得到一个英文字符的 ASCII 码,或者一个汉字字符的 Unicode 码,或者从相关的编码查询它是哪一个字符的编码。很多人,尤其是从 VB 程序序转过来学 C# 的人,会报怨 C# 里为什么没有提供现成的函数来做这个事情——因为在 VB 中有 Asc() 函数和 Chr() 函数用于这类转换。 private void TestChar() { char ch = 'a'; short ii = 65; 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"); } 它的运行结果是
从这个例子中,我们便能非常清楚的了解——通过强制转换,可以得以字符的编码,或者得到编码表示的字符。如果你需要的不是 short 型的编码,请参考第 1 条进行转换,即可得到 int 等类型的编码值。 4. 数值字符串和数值之间的转换 首先,我们得搞明白,什么是数值字符串。我们知道,在 C# 中,字符串是用一对双引号包含的若干字符来表示的,如 "123"。而 "123" 又相对特殊,因为组成该字符串的字符都是数字,这样的字符串,就是数值字符串。在我们的眼中,这即是一串字符,也是一个数,但计算机却只认为它是一个字符串,不是数。因此,我们在某些时候,比如输入数值的时候,把字符串转换成数值;而在另一些时候,我们需要相反的转换。 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."); } } 运行结果:
5. 字符串和字符数组之间的转换 字符串类 System.String 提供了一个 void ToCharArray() 方法,该方法可以实现字符串到字符数组的转换。如下例: private void TestStringChars() { string str = "mytest"; char[] chars = str.ToCharArray(); 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"); } 例中以对转换转换到的字符数组长度和它的一个元素进行了测试,结果如下:
可以看出,结果完全正确,这说明转换成功。那么反过来,要把字符数组转换成字符串又该如何呢?
运行结果输入 tstr = "test me",测试说明转换成功。
正确的输出是 "test me"[3] = t,经测试,输出正确。 6. 字符串和字节数组之间的转换 如果还想从 System.String 类中找到方法进行字符串和字节数组之间的转换,恐怕你会失望了。为了进行这样的转换,我们不得不借助另一个类:System.Text.Encoding。该类提供了 bye[] GetBytes(string) 方法将字符串转换成字节数组,还提供了 string GetString(byte[]) 方法将字节数组转换成字符串。 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"); } 运行结果如下,不说详述,相信大家已经明白了。
将字节数组转换成字符串,使用 Encoding 类的 string GetString(byte[]) 或 string GetString(byte[], int, int) 方法,具体使用何种 Encoding 还是由编码决定。在 TestStringBytes() 函数中添加如下语句作为实例:
运行结果为:The string is: abcdef 7. 各种数值类型和字节数组之间的转换 在第 1 条中我们可以查到各种数值型需要使用多少字节的空间来保存数据。将某种数值类型的数据转换成字节数组的时候,得到的一定是相应大小的字节数组;同样,需要把字节数组转换成数值类型,也需要这个字节数组大于相应数值类型的字节数。 由于这类转换通常只是在需要进行较细微的编码/解码操作时才会用到,所以这里就不详细叙述了,仅把 System.BitConverter 类介绍给大家。 8. 转换成十六进制 任何数据在计算机内部都是以二进制保存的,所以进制与数据的存储无关,只与输入输出有关。所以,对于进制转换,我们只关心字符串中的结果。 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"); } 运行结果如下:
这时候,我们可能有另一种需求,即为了显示结果的整齐,我们需要控制十六进制表示的长度,如果长度不够,用前导的 0 填补。解决这个问题,我们只需要在格式说明符“x”或者“X”后写上表示长度的数字就行了。比如,要限制在 4 个字符的长度,可以写成“X4”。在上例中追加一句:
其结果将输出 a(16) = 00BC。 9. 日期型数据和长整型数据之间的转换 为什么要将日期型数据转换为长整型数据呢?原因很多,但就我个人来说,经常将它用于数据库的日期存储。由于各种数据库对日期型的定义和处理是不一样的,各种语言对日期型数据的定义的处理也各不相同,因为,我宁愿将日期型数据转换成长整型再保存到数据库中。虽然也可以使用字符串来保存,但使用字符串也会涉及到许多问题,如区域等问题,而且,它需要比保存长整型数据更多的空间。
DateTime 的构造函数中也提供了相应的,从长整型数据构造 DateTime 型数据的函数:DateTime(long)。如:
但这样对于很多 VB6 程序员来说,是给他们出了一道难题,因为 VB6 中的日期型数据内部是以 Double 型表示的,将其转换为长整型后得到的仅仅是日期,而没有时间。如何协调这两种日期类型呢? private void TestDateTimeLong() { double doubleDate = DateTime.Now.ToOADate(); DateTime theDate = DateTime.FromOADate(doubleDate); this.textBox1.Text = ""; this.textBox1.AppendText("Double value of now: " + doubleDate.ToString() + "/n"); this.textBox1.AppendText("DateTime from double value: " + theDate.ToString() + "/n"); } 运行结果:
10. 格式化日期型数据 编程的过程中,通常需要将日期型数据按照一定的格式输出,当然,输出结果肯定是字符串。为此,我们需要使用 System.DateTime 类的 ToString() 方法,并为其指定格式字符串。
为了便于大家的理解,不妨试试下面的程序: 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"); } 这段程序将输出结果:
这时候,又出现一个问题,如果要输出的文本信息中包含格式字符怎么办?如
将输出:
这并不是我想要的结果,怎么办呢?有办法——
看,这次运行结果对了:
可以看出,只需要使用单引号或者双引号将文本信息括起来就好。 |