C#程序设计自学经典
上QQ阅读APP看书,第一时间看更新

2.4 字符与字符串的处理

本节主要讲解字符和字符串的处理。C#中对于文字的处理大多数是通过对字符和字符串的操作来实现。本节通过字符与字符串的定义、使用以及它们之间的区别、常见的字符串的处理方法,以及可变字符串类的定义及使用,详细地介绍字符与字符串的相关内容。

2.4.1 char的使用

1.char简介

char关键字用于声明.NET Framework中使用Unicode字符表示System.Char结构的实例。Char对象的值是16位数字(序号值)。

Unicode字符是16位字符,用于表示世界上大多数已知的书面语言。与C++中的char不一样,C#中的char的长度不是一个字节,而是两个字节。char表示一个16位的Unicode字符。

char的声明与初始化:

    char 变量名 = '变量值';

例如:

    char char1='T';
    char char2='9';

2.Char类的应用

Char类提供了丰富的操作字符的方法,Char类的方法及说明如表2-7所示。

表2-7 Char类的方法及说明

续表

使用这些方法可以方便地操作字符,下面通过一个小例子演示如何使用Char类提供的这些方法。

例2-3:使用Char类方法操作字符(ConsoleCharClass)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleCharClass
    {
        class Program
        {
            static void Main(string[] args)
            {
                //声明字符a到g
                char a = 'a';
                char b = 'M';
                char c = '6';
                char d = '.';
                char e = '☆';
                char f = '|';
                char g = ' ';
    
                //使用IsLetter方法判断变量a是否为字母
                Console.WriteLine("IsLetter方法判断变量a是否为字母:{0}", Char. 
                IsLetter(a));
    
                //使用IsLetterOrDigit方法判断变量b是否为字母或数字
                Console.WriteLine("IsLetterOrDigit方法判断变量b是否为字母或数字:
               {0}", Char.IsLetterOrDigit(b));
    
                //使用IsDigit方法判断变量c是否为十进制数字
                Console.WriteLine("IsDigit方法判断变量c是否为十进制数字:{0}", 
                Char.IsDigit(c));
    
                //使用IsLower方法判断变量a是否为小写字母
                Console.WriteLine("IsLower方法判断变量a是否为小写字母:{0}", Char. 
                IsLower(a));
    
                //使用IsUpper方法判断变量b是否为大写字母
                Console.WriteLine("IsUpper方法判断变量b是否为大写字母:{0}", Char. 
                IsUpper(b));
    
                //使用IsPunctuation方法判断变量d是否为标点符号
                Console.WriteLine("IsPunctuation方法判断变量d是否为标点符号:{0}", 
                Char.IsPunctuation(d));
    
                //使用IsSymbol方法判断变量e是否为符号
                Console.WriteLine("IsSymbol方法判断变量e是否为符号:{0}", Char. 
                IsSymbol(e));
    
                //使用IsSeparator方法判断变量f是否为分隔符
                Console.WriteLine("IsSeparator方法判断变量f是否为分隔符:{0}", 
                Char.IsSeparator(f));
    
                //使用IsWhiteSpace方法判断变量g是否为空白
                Console.WriteLine("IsWhiteSpace方法判断变量g是否为空白:{0}", 
                Char.IsWhiteSpace(g));
                Console.ReadLine();
            }
        }
    }

程序运行结果如图2-6所示。

图2-6 使用Char类方法操作字符

3.转义字符

转义字符是一种特殊的字符常量;C#中采用字符“\”作为转义字符。它具有特定的含义,不同于字符原有的意义,故称为“转义”字符。转移字符具有以下特点。

(1)以反斜线“\”开头,后跟一个或多个字符。

(2)转义字符主要用来表示那些用一般字符不便于表示的控制代码。

(3)它的作用是消除紧随其后的字符的原有含义。

(4)用可以看见的字符表示那些不可以看见的字符,如'\n'表示换行。

表2-8列出了一些常用的转义字符及其含义。

表2-8 转义字符及其含义

下面通过一个小例子来了解转义符的应用。

例2-4:转义符的应用(ConsoleEscapeCharacter)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleEscapeCharacter
    {
        class Program
        {
            static void Main(string[] args)
            {
                string name, address, age;
                Console.Write("请输入您的姓名:");
                name = Console.ReadLine();
                Console.Write("请输入您的年龄:");
                age = Console.ReadLine();
                Console.Write("请输入您的出生地:");
                address = Console.ReadLine();
                Console.WriteLine("您的基本信息如下:");
                Console.WriteLine("姓名\t年龄\t出生地");
                Console.WriteLine("{0}\t{1}\t{2}", name, age, address);
                Console.ReadLine();
            }
        }
    }

程序运行结果如图2-7所示。

图2-7 转义符的应用

2.4.2 字符串类String的使用

字符串是应用程序中最常用的一种数据类型。C#中专门处理字符串的String类,位于System命名空间中,我们一直使用的string只不过是String类的一个别名。

1.String类的使用

C#中string与C++一样,都是由多个char组成。也就是说,C#中的string也是由多个16位的Unicode字符组成。

字符串是Unicode字符的有序集合,用于表示文本。String对象是System.Char对象的有序集合,用于表示字符串。String对象的值是该有序集合的内容,并且该值是不可变的。正是因为字符构成了字符串,根据字符在字符串中的不同位置,字符在字符串中有一个索引值,可以通过索引值获取字符串中的某个字符。字符在字符串中的索引从零开始。例如,字符串“hellow”中的第一个字符为h,而“h”在字符串中的索引顺序为0。需要注意的是,String类所定义的变量是一个引用类型,可以对String类型的变量进行null赋值。

例2-5:字符串中字符的获取

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleGetCharByString
    {
        class Program
        {
            static void Main(string[] args)
            {
                //声明一个字符串变量
                string str = "Hello World!";
                //获取字符串str的第2个字符
                char char1 = str[1];
                //获取字符串str的第3个字符
                char char2 = str[2];
                //获取字符串str的第7个字符
                char char3 = str[6];
                //输出
                Console.WriteLine("字符串str中的第二个字符是:{0}", char1);
                Console.WriteLine("字符串str中的第三个字符是:{0}", char2);
                Console.WriteLine("字符串str中的第七个字符是:{0}", char3);
                Console.ReadLine();
            }
        }
    }

程序运行结果如图2-8所示。

图2-8 字符串中字符的获取

代码中采取在字符串变量后加一个方括号,并在方括号里面给出索引值的方法获取相应的字符。这是数组变量通用的索引方法。str[1]获取的是字符串变量str的第二个字符。

2.常用的字符串处理方法

C#中提供了比较丰富的字符串处理方法,表2-9中列出了一些常用的字符串处理方法和每个方法接收的参数和返回值及其说明。

表2-9 常用字符串处理方法

1)比较字符串

C#中最常见的比较字符串的方法有Equals、Compare、CompareTo和CompareOrdinal,这些方法都属于String类。下面就分别对这4种方法进行详细介绍。

(1)Equals方法

Equals方法通常用来比较两个对象的值是否相等,如果相同返回true,否则返回false。其常用的两种语法如下:

    public bool Equals(string value)
    public static bool Equals(string a,string b)

其中,value是与实例比较的字符串,a和b是要进行比较的两个字符串。

例2-6:使用Equals比较字符串(ConsoleEquals)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleEquals
    {
        class Program
        {
            static void Main(string[] args)
            {
                string str1 = "Hello World!";
                string str2 = "HelloWorld!";
                Console.WriteLine(str1.Equals(str2));
                Console.WriteLine(String.Equals(str1, str2));
                Console.ReadLine();
            }
        }
    }

程序运行结果如图2-9所示。

图2-9 使用Equals比较字符串

补充:

运算符==和String类方法Equals()的区别如下。

① ==通常用来比较int、double等数值类型的数据是否相等。

② Equals()通常用来比较两个对象的值是否相等。

“”和String.Empty()的区别如下。

① “”为String对象分配长度为0的内存空间。

② String.Empty()不会为对象分配内存空间。

(2)Compare方法

Compare方法用来比较两个字符串是否相等,它有很多个重载方法,其中最常用的方法如下。

    static Int Compare(string a,string b)
    static Int Compare(string a,string b,bool ignorCase)

其中,a和b代表要比较的两个字符串。

ignorCase如果是true,那么在比较字符串时就忽略大小写的差别。

下面通过一个小实例来演示Compare方法的使用。

例2-7:使用Compare比较字符串(ConsoleCompare)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleCompare
    {
        class Program
        {
            static void Main(string[] args)
            {
                string str1 = "Hello World!";
                string str2 = "HelloWorld!";
                Console.WriteLine(string.Compare(str1, str2));
                Console.WriteLine(string.Compare(str2, str1));
                Console.WriteLine(String.Compare(str1, str1));
                Console.ReadLine();
            }
        }
    }

程序运行结果如图2-10所示。

图2-10 使用Compare比较字符串

关键点解析:

比较字符串并非比较字符串长度的大小,而是比较字符串在英文字典中的位置。比较字符串按照字典排序规则判断两个字符串的大小,在英文字典中,前面的单词小于后面的单词。

(3)CompareTo方法

CompareTo方法与Compare方法类似,都可以比较两个字符串是否相等,不同的是CompareTo方法以实例对象本身指定的字符串做比较,其语法如下:

    public  int CompareTo(string a)

下面通过一个小实例来演示CompareTo方法的使用。

例2-8:使用CompareTo比较字符串(ConsoleCompareTo)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleCompareTo
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                string str1 = "你好啊";
                string str2 = "你好";
                Console.WriteLine(str1.CompareTo(str2));
                Console.ReadLine();
            }
        }
    }

程序运行结果如图2-11所示。

图2-11 使用CompareTo比较字符串

(4)CompareOrdinal方法

CompareOrdinal方法对两个字符串进行比较,不考虑本地化语言和文化。其中常用的语法如下:

    public static CompareOrdinal(string a,string b)

下面通过一个小实例来演示CompareOrdinal方法的使用。

例2-9:使用CompareOrdinal比较字符串(ConsoleCompareOrdinal)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleCompareOrdinal
    {
        class Program
        {
            static void Main(string[] args)
            {
                string str1 = "Hello Worlda";
                string str2 = "Hello WorldA";
                Console.WriteLine(string.CompareOrdinal(str1, str2)); 
                Console.ReadLine();
            }
        }
    }

程序运行结果如图2-12所示。

图2-12 使用CompareOrdinal比较字符串

2)截取字符串

String类提供了Substring方法,该方法用于截取字符串中指定位置和指定长度的字符。其语法格式如下:

    public string Substring(int startIndex,int length)

其中,startIndex代表子字符串的起始位置的索引,length代表要截取的子字符串的字符串。

例2-10:使用Substring截取字符串(ConsoleSubstring)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleSubstring
    {
        class Program
        {
            static void Main(string[] args)
            {
                string str1 = "HelloWorld!";
                string str2 = str1.Substring(5, 6);
                Console.WriteLine(str2);
                Console.ReadLine();
    
            }
        }
    }

程序运行结果如图2-13所示。

图2-13 使用Substring截取字符串

3)IndexOf方法取索引

IndexOf方法报告指定的字符在此实例中的第一个匹配项的索引。搜索从指定字符位置开始,并检查指定数量的字符位置。

其语法格式如下:

    public int IndexOf(value, [startIndex], [count])

其中,

value:要查找的Unicode字符。对value的搜索区分大小写。

startIndex(Int32):可选项,搜索起始位置。不设置则从0开始。

count(Int32):可选项,要检查的字符位数。

下面通过一个实例来演示IndexOf的使用。

例2-11:使用IndexOf获取指定字符串索引(ConsoleIndexOf)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleIndexOf
    {
        class Program
        {
            static void Main(string[] args)
            {
                string str1 = "HelloWorld!";
                string str2 = "o";
                Console.WriteLine(str1.IndexOf(str2));
                Console.WriteLine(str1.IndexOf(str2, 5));
                Console.WriteLine(str1.IndexOf(str2, 0, 4));
                Console.ReadLine();
    
            }
        }
    }

程序运行结果如图2-14所示。

图2-14 使用IndexOf获取指定字符串索引

4)连接字符串

C#中连接字符串使用String类的Join()方法。

其语法格式如下:

    public string Join(string value,string[] args)

其中,value为连接字符串的连接符,args为要连接的string数组对象。

在指定的args数组的每个元素之间串联指定的分隔符value,从而产生单个串联的字符串。

例2-12:使用Join连接字符串(ConsoleJoin)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleJoin
    {
        class Program
        {
            static void Main(string[] args)
            {
                string str1 = "-";
                string[] strs = new string[] { "hi", "china", "hello", "world" };
                Console.WriteLine(string.Join(str1, strs));
                Console.ReadLine();
    
            }
        }
    }

程序运行结果如图2-15所示。

图2-15 使用Join连接字符串

5)分割字符串

String类提供了一个用于分割字符串的Split方法,该方法的返回值是包含所有分割子字符串的数组对象。

其语法格式如下:

    public string[] Split(params char[] separator)
    public string[] Split(char[] separator, int count)
    public string[] Split(char[] separator, StringSplitOptions options)
    public string[] Split(string[] separator, StringSplitOptions options)
    public string[] Split(char[] separator, int count, StringSplitOptions options)
    public string[] Split(string[] separator, int count, StringSplitOptions options)

例2-13:使用Split分割字符串(ConsoleSplit)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleSplit
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                string str1 = "a,b.c,,d,e";
                //1. public string[] Split(params char[] separator)
                string[] split1 = str1.Split(new Char[] { ',' });
                string[] split2 = str1.Split(new Char[] { ',', '.' });
                foreach (string s in split1)
                {
                    Console.Write(s + "#");
                }
                Console.WriteLine();
                foreach (string s in split2)
                {
                    Console.Write(s + "#");
                }
                //2. public string[] Split(char[] separator, int count)
    
                string[] split3 = str1.Split(new Char[] { ',', '.' }, 2);
                string[] split4 = str1.Split(new Char[] { ',', '.' }, 6);
                Console.WriteLine();
                foreach (string s in split3)
                {
                    Console.Write(s + "#");
                }
                Console.WriteLine();
                foreach (string s in split4)
                {
                    Console.Write(s + "#");
                }
                //3. public string[] Split(char[] separator, StringSplitOptions 
                options)
                string[] split5 = str1.Split(new Char[] { ',', '.' }, 
                StringSplitOptions.RemoveEmptyEntries);
                string[] split6 = str1.Split(new Char[] { ',', '.' }, 
                StringSplitOptions.None);
                Console.WriteLine();
                foreach (string s in split5)
                {
                    Console.Write(s + "#");
                }
                Console.WriteLine();
                foreach (string s in split6)
                {
                    Console.Write(s + "#");
                }
                //4. public string[] Split(string[] separator, 
                StringSplitOptions options)
                string[] split7 = str1.Split(new string[] { ",", "." }, 
                StringSplitOptions.RemoveEmptyEntries);
                //返回:{"1","2","3","4"} 不保留空元素
                string[] split8 = str1.Split(new string[] { ",", "." }, 
                StringSplitOptions.None);//返回:{"1","2","3","","4"} 保留空元素
                Console.WriteLine();
                foreach (string s in split7)
                {
                    Console.Write(s + "#");
                }
                Console.WriteLine();
                foreach (string s in split8)
                {
                    Console.Write(s + "#");
                }
                //5. public string[] Split(char[] separator, int count, 
                StringSplitOptions options)
    
                string[] split9 = str1.Split(new Char[] { ',', '.' }, 2, 
                StringSplitOptions.RemoveEmptyEntries);
                string[] split10 = str1.Split(new Char[] { ',', '.' }, 6, 
                StringSplitOptions.None);
                Console.WriteLine();
                foreach (string s in split9)
                {
                    Console.Write(s + "#");
                }
                Console.WriteLine();
                foreach (string s in split10)
                {
                    Console.Write(s + "#");
                }
    
                //6. public string[] Split(string[] separator, int count, 
                StringSplitOptions options)
    
                string[] split11 = str1.Split(new string[] { ",", "." }, 2, 
                StringSplitOptions.RemoveEmptyEntries);
                string[] split12 = str1.Split(new string[] { ",", "." }, 6, 
                StringSplitOptions.None);
                Console.WriteLine();
                foreach (string s in split11)
                {
                    Console.Write(s + "#");
                }
                Console.WriteLine();
                foreach (string s in split12)
                {
                    Console.Write(s + "#");
                }
    
                Console.ReadLine();
    
            }
        }
    }

程序运行结果如图2-16所示。

图2-16 使用Split分割字符串

关键点解析:

代码中使用foreach循环输出数组的每个元素,并用#号连接,目的是使读者能更清晰地看到执行结果。foreach语句将在后续章节进行介绍,在此不作为重点内容。

需要注意的是没有重载函数public string[] Split(string[] separator),所以不能像VB.NET那样使用words.Split(","),而只能使用words.Split(',')。很多读者都很奇怪为什么把双引号改为单引号就可以了?看了上边的重载函数就应该知道答案了。

6)替换字符串

String类提供了一个Replace的方法,该方法用于将字符串中的某个字符或字符串替换成其他的字符或字符串。

其语法格式如下:

    public string Replace(char oldChar,char newChar)
    public string Replace(string oldStr,string newStr)

第一个参数为待替换的字符或字符串,第二个参数为替换后的新字符或新字符串。

第一种语法格式主要用于替换字符串中指定的字符,第二种语法格式主要用于替换字符串中指定的字符串。

下面通过一个小实例来演示Replace的使用。

例2-14:使用Replace替换字符串(ConsoleReplace)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleReplace
    {
        class Program
        {
            static void Main(string[] args)
            {
                string str1 = "hello world.";
                string str2 = str1.Replace('.', '!');
                Console.WriteLine(str2);
                string str3 = str1.Replace("world", "Tom");
                Console.WriteLine(str3);
                Console.ReadLine();
    
            }
        }
    }

程序运行结果如图2-17所示。

图2-17 使用Replace替换字符串

7)格式化字符串

在C#中,String类提供了一个静态的Format方法,用于将字符串数据格式化成指定的格式。

其语法格式如下:

    public static string Format(string format,object obj)

其中,format是用来指定字符串所要格式化的形式,obj则是要被格式化的对象。

例2-15:使用Format格式化字符串(ConsoleFormat)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleFormat
    {
        class Program
        {
            static void Main(string[] args)
            {
                string str1 = "你好";
                string str2 = "中国";
                string newStr = string.Format("{0},{1}!!", str1, str2);
                Console.WriteLine(newStr);
                Console.ReadLine();
    
            }
        }
    }

程序运行结果如图2-18所示。

图2-18 使用Format格式化字符串

表2-10列出了Format()方法的格式字符串中各种格式化定义字符和示例。

表2-10 格式化数值结果

如果需要按某种格式输出日期时间,那么可以使用Format方法将日期时间格式化后再输出,表2-11列出了格式化日期时间的格式规范。

表2-11 格式化日期时间

例2-16:使用Format格式化日期时间(ConsoleFormatDateTime)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleFormatDateTime
    {
        class Program
        {
            static void Main(string[] args)
            {
                DateTime dt = DateTime.Now;
                string str1 = String.Format("{0:t}", dt);
                Console.WriteLine(str1);
                Console.ReadLine();
    
            }
        }
    }

程序运行结果如图2-19所示。

图2-19 使用Format格式化日期时间

3.类型转换

1)简单的类型转换

在C#中简单的类型转换包括隐式类型转换和显式类型转换。下面就简单介绍这两种类型转换。

(1)隐式类型转换

对于任何数值类型A来说,只要其取值范围完全包含在类型B的取值范围内,就可以隐式转换为类型B。也就是说,int类型可以隐式转换为float类型或double类型,float类型也可以隐式转换为double类型。

(2)显式类型转换

显式类型转换与隐式类型转换相反,当要把取值范围大的类型转换为取值范围小的类型时,就需要执行显式转换了。

下面通过一个小例子来了解下显式类型转换。

例2-17:显式类型转换(ConsoleConvert)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleConvert
    {
        class Program
        {
            static void Main(string[] args)
            {
                //文化课成绩
                double score = 73.5;
                //艺术课加分
                int bonus = 43;
                //总分
                int sum = (int)score + bonus;
    
                Console.WriteLine("文化课成绩:{0}分", score);
                Console.WriteLine("艺术课加分:{0}分", bonus);
                Console.WriteLine("总分:{0}分", sum);
                Console.ReadLine();
            }
        }
    }

程序运行结果如图2-20所示。

图2-20 显式类型转换

关键点解析:

从运行结果中不难看出,变量score的值仍然是73.5,但sum的值却变成了116。这是因为在计算加法时,将score的值转换为73进行计算,丢失了精度所致。尽管对变量score进行了强制类型转换,但实际上score的值并没有改变,只是在计算时临时转换成整数参与表达式的计算。

2)数值类型与字符串类型的转换

隐式类型转换和显式类型转换一般都用在数值类型之间,并不适用于数值类型以及字符串之间的转换。下面就介绍一下数值类型与字符串类型之间的互相转换。

(1)字符串转换为数值类型

C#中提供了各种类型的Parse()方法来进行类型转换。

例如,将字符串转为整型代码为:

    int.Parse(strValue);

将字符串转为float型代码为:

    float.Parse(strValue);

将字符串转为double型代码为:

    double.Parse(strValue);

此处的strValue必须是数字的有效表示形式。简单地讲就是看起来是对应的数字,但实际上是string类型。例如,可以把“5555”转换为整数,而不能把“zhangsan”等转换为整数。

(2)数值类型转换为字符串

在C#中,数值类型转换为字符串非常简单,只要调用其ToString()方法就可以了。例如:

    int num=521;
    string strNum=num. ToString();

除此之外,还可以使用“+”连接符拼接一个空的字符串实现相同的效果,例如:

    int num=521;
    string strNum=num+"";

3)使用Convert类进行转换

除了使用Parse()方法外,还可使用Convert类进行转换。Convert类可以在各种基本类型之间执行数据类型的互相转换,它为每种类型转换都提供了一个对应的方法。表2-12为Convert类的常用方法。

表2-12 Convert类的常用方法

方法中的参数就是需要进行转换的数值。

下面通过一个小例子来了解下如何使用Convert类进行转换。

例2-18:使用Convert类进行转换(ConsoleConvertClass)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleConvertClass
    {
        class Program
        {
            static void Main(string[] args)
            {
                double dNum = 76.74;
                int iNum;
                decimal decimalNum;
                float fNum;
                string sNum;
                bool flag;
    
                iNum = Convert.ToInt32(dNum);
                decimalNum = Convert.ToDecimal(dNum);
                fNum = Convert.ToSingle(dNum);
                sNum = Convert.ToString(dNum);
                flag = Convert.ToBoolean(dNum);
    
                Console.WriteLine("原数值为double类型:" + dNum);
    
                Console.WriteLine("转换后为:");
                Console.WriteLine("int类型:\t" + iNum);
                Console.WriteLine("decimal类型:\t" + decimalNum);
                Console.WriteLine("float类型:\t" + fNum);
                Console.WriteLine("string类型:\t" + sNum);
                Console.WriteLine("bool类型:\t" + flag);
    
                Console.ReadLine();
            }
        }
    }

程序运行结果如图2-21所示。

图2-21 使用Convert类进行转换

关键点解析:

从运行结果中可以看出,转换为int类型时,进行了四舍五入的计算,所以结果为77,这与显式类型转换有所不同,如果使用显式类型转换将76.74转换为int类型的结果是76,它是直接将小数点后的数值舍弃掉了。转换为bool类型的时候,只要转换的值不为0,那么结果就是true,否则为false。

2.4.3 可变字符串类StringBuilder的使用

我们知道String类有很多实用的处理字符串的方法,但是在使用String类时常常存在这样一个问题:当每次为同一个字符串重新赋值时,都会在内存中创建一个新的字符串对象,需要为该对象分配新的内存空间,这样会加大系统的开销。因为System.String类是一个不可变的数据类型,一旦对一个字符串对象进行初始化后,该字符串对象的值就不能改变了。当对该字符串的值做修改时,实际上是又创建了一个新的字符串对象。比如下面的小例子:

    String str1="Hello";
    str1+="World"
    Console.WriteLine(str1);

上面这段代码的输出结果是"HelloWorld"。但是,这段代码创建了几个对象呢?下面逐句分析一下。

首先,String str1="Hello";创建了一个对象,值为"Hello"。

str1+="World"通过+=赋值运算符为该对象赋值。执行此句时,从表面上看str1的值更新了,实际上内存中又创建了两个新对象,其值分别为"World"和"HelloWorld!"。此时内存中存在三个对象:Hello、World和HelloWorld。而str1所引用的是HelloWorld对象,其他对象没有实际作用。如此反复的操作会使系统内存占用很大,造成不必要的浪费,大大降低了程序运行性能。如何解决此问题呢?

为了解决以上问题,Microsoft提供了System.Text.StringBuilder类,此类表示可变字符串。虽然StringBuilder类像String类一样具有很多处理字符串的方法,但是在添加、删除或替换字符串时,StringBuilder类对象的执行速度要远比String类快得多。

下面来看一下StringBuilder类的定义。StringBuilder类有6种不同的构造方法。在此只讲解比较常用的两种:

    StringBuilder sbValue=new StringBuilder();

此种方法声明了一个空的StringBuilder对象。

    StringBuilder sbValue=new StringBuilder("HelloWorld");

此种方法声明一个StringBuilder对象,其值为“HelloWorld”。

在使用StringBuilder类时先要引用其命名空间System.Text。表2-13为StringBuilder类的常用属性、方法及说明。

表2-13 StringBuilder类的常用属性、方法及说明

下面通过一个小例子来演示如何使用StringBuilder类。

例2-19:使用StringBuilder类(ConsoleStringBuilder)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleStringBuilder
    {
        class Program
        {
            static void Main(string[] args)
            {
                StringBuilder sb = new StringBuilder();
    
                sb.AppendLine("明月几时有?");
                sb.AppendLine("把酒问青天。");
                sb.AppendLine("不知天上宫阙,");
                sb.AppendLine("今夕是何年?");
                sb.AppendLine("我欲乘风归去,");
                sb.AppendLine("又恐琼楼玉宇,");
                sb.AppendLine("高处不胜寒。");
                sb.AppendLine("起舞弄清影,");
                sb.AppendLine("何似在人间?");
                sb.AppendLine("转朱阁,");
                sb.AppendLine("低绮户,");
                sb.AppendLine("照无眠。");
                sb.AppendLine("不应有恨、");
                sb.AppendLine("何事长向别时圆?");
                sb.AppendLine("人有悲欢离合,");
                sb.AppendLine("月有阴晴圆缺,");
                sb.AppendLine("此事古难全。");
                sb.AppendLine("但愿人长久,");
                sb.AppendLine("千里共婵娟。");
                sb.Insert(0, "《水调歌头·中秋》\n\n");
                int count = sb.Capacity;
                sb.Insert(sb.Length, "\t\t——苏轼");
                sb.Append("\t(字符数为:" + count + ")");
                Console.WriteLine(sb.ToString());
                Console.ReadLine();
            }
        }
    }

程序运行结果如图2-22所示。

图2-22 使用StringBuilder类

关键点解析:

    sb.Insert(0, "《水调歌头·中秋》\n\n");

此句在所有字符前面插入“《水调歌头·中秋》\n\n”字符串。

    sb.Insert(sb.Length, "\t\t——苏轼");

此句得到当前StringBuilder对象的长度并在此长度后将字符串“\t\t——苏轼”添加到当前对象中的sb.Length位置上。

最后通过ToString方法把StringBuilder对象转成String类型。