string关键字表示一个字符串(零个或更多 Unicode 字符),它对应.NET的System.String。请注意,我们在前面的章节中所学习的bool、byte、short、int、long、float、double、decimal等基础数据类型都是值类型,因为它们都是以struct关键字声明和定义的,而string则是由class关键字声明和定义的,所以,string并不是一个值类型,而是引用类型。

尽管string是引用类型,它的值会存储在托管堆内存中,但在实际的使用过程中,它看起来像值类型一样。例如可以使用相等运算符(== 和 !=)进行比较,或者两个字符串相加变成一个字符串。

观察下面的例子

static void Main(string[] args)
 
 {
 
     string name = "李";
 
     name = name + "莫愁";
 
     Console.WriteLine($"name = {name}"); 
 
     Console.ReadKey();
 
 }

输出结果:name = 李莫愁

由此可见,我们先定义一个叫name的字符串变量,并赋值为字符串"李",然后加了一个字符串"莫愁",最后将这个变量的值打印出来,所以是"李莫愁"。看起来我们是修改了name的值。

实际上,字符串的值是不可以修改的!

咦,这句话怎么理解?字符串对象name被创建后,会在内存中开辟一个空间(假定地址a),当执行 name = name + "莫愁" 这句话时,编译器实际上会创建一个新字符串对象来保存新的字符序列,再将新对象赋给 name变量,而name变量的地址一直不变,只是值发生了改变。最后字符串”李“将被无情的遗忘,由.NET垃圾回收器在适当的时候进行内存回收。

我们再看看字符串对比是否相等的例子

static  void Main(string[] args)
 
 {
 
     string a = "hello";
 
     string b = "h";            
 
     b += "ello";
 
     Console.WriteLine(a == b);
 
     Console.WriteLine((object)a == (object)b);
 
  
 
     Console.ReadKey();
 
 }

输出结果:

True
False

这里说明字符串的值是可以直接对比的,但是两个字符串变量由于不是引用同一个字符串实例,所以二者是不等的。

关于字符串的几种形式

1、普通字符串:使用双引号引起来。

string name = "李莫愁";                 
 
 Console.WriteLine($"name = {name}");

2、转义字符串:

string name = "李莫愁\n外号赤练仙子";          
 
 Console.WriteLine($"name = {name}");

输出结果

name = 李莫愁
外号赤练仙子

这次在字符串中间增加了\n,表示换行,所以输出结果变成了两行。以\开头的表示转义字符,例如:

转义字符

意义

ASCII码值(十进制)

\a

响铃(BEL)

007

\b

退格(BS) ,将当前位置移到前一列

008

\f

页(FF),将当前位置移到下页开头

012

\n

换行(LF) ,将当前位置移到下一行开头

010

\r

回车(CR) ,将当前位置移到本行开头

013

\t

水平制表(HT) (跳到下一个TAB位置)

009

\v

垂直制表(VT)

011

\\

代表一个反斜线字符"\"

092

\'

代表一个单引号(撇号)字符

039

\"

代表一个双引号字符

034

\?

代表一个问号

063

\0

空字符(NUL)

000

\ddd

1到3位八进制数所代表的任意字符

三位八进制

\xhh

十六进制所代表的任意字符

十六进制

3、带@的原义字符串

string name = @"李莫愁\n外号赤练仙子";       
 
 Console.WriteLine($"name = {name}");

输出结果:

name = 李莫愁\n外号赤练仙子

这次\n失去了作用,被当作普通字符输出,这是因为在字符串的前面加了一个@。使整个字符串变成了原义字符串。

4、参数字符串

$"name = {name}"

这时我们在字符串前面增加了一个$美元符号,双引号中间可以使用大括号将某个变量括起来,最后使用这个字符串时,大括号里面的内容会替换成变量的值。

字符串是区分大小写的,观察下面的例子

string a = "\u0068ello ";
 
 string b = "world";
 
 Console.WriteLine(a + b);
 
 Console.WriteLine(a + b == "hello world"); 
 
 Console.WriteLine(a + b == "Hello world");

输出结果

hello world
True
False

创建字符串的几种方式

static  void Main(string[] args)
 
 {
 
     //第一种 字符串连接
 
     string fname, lname;
 
     fname = "赤练仙子";
 
     lname = "李莫愁";
 
     string fullname = fname + lname;
 
     Console.WriteLine("全名: {0}", fullname);
 
  
 
  
 
     //第二种 构造函数
 
     char[] words = { '赤', '练', '仙', '子', '李', '莫', '愁' };
 
     string word = new string(words);
 
     Console.WriteLine("全称: {0}", word);
 
  
 
     //第三种 方法返回字符串
 
     string[] array = { "赤练仙子", "李莫愁" };
 
     string message = string.Join("-", array);
 
     Console.WriteLine("称号: {0}", message);
 
  
 
     //第四种 Format格式化
 
     string date = string.Format("日期:{0:D} 时间:{0:t}", DateTime.Now);
 
     Console.WriteLine(date);
 
  
 
     Console.ReadKey();
 
 }

输出结果

全名: 赤练仙子李莫愁
全称: 赤练仙子李莫愁
称号: 赤练仙子-李莫愁
日期:2024年1月20日 时间:11:00

——重庆教主 2024年1月20日