C#字符串

字符串由0或多个的字符组成的一串文本。

在C#中,使用string类型表示字符串。

初始化字符串

通过双引号,可以创建字符串直接量。

string s = "Hello World";

转义字符

有些字符是不能直接输入的,如果要在C#中使用,需要用到转义字符。

转义字符使用反斜杠\开始,后面跟字母。

转义字符 说明
\n 换行
\t 水平制表符
\\ 反斜杠自身
\" 双引号自身
\r 回车

在windows下新行通常使用\r\n,在linux下,新行通常使用\n。通过Environment.NewLine可以获取系统默认换行符。

逐字字符串

使用@开始的字符串是逐字字符串,表示其中的反斜杠不作为转义字符使用。

逐字字符串支持多行。

在逐字字符串中,要表示双引号本身,要使用两个双引号。

string s = @"\r\n";
string s2 = @"""ok""";
string s3 = @"line1
line2";

基本操作

Length属性。获取字符串的长度,长度为0表示是空字符串。

char this[int index]{get;}。获取字符串指定索引处的字符。

static readonly string Empty。一个只读字符串,表示空字符串。

字符串是不可变的,一旦创建就不可以再修改了。

字符串相关的方法都会返回一个新字符串。

格式化

static string string.Format(string format,params object[] args)

根据参数替换格式字符串的占位符。

格式字符串中可以使用{索引:格式}作为占位符。索引从0开始,不能大于参数数量。

在结果中,对应占位符会被对应参数的字符串形式替换。

占位符中的格式如果没有设置,调用的是对应参数的ToString()方法,如果设置了,调用对应类型的ToString(string format)方法。

如果要输出花括号自身,要使用两个花括号。

int a=1,b=2;
string s1 = string.Format("{0}+{1}={2}",a,b,a+b);//1+2=3
string s2= string.Format("{0:f4}",3.1415927);//3.1416
string s3 = string.Format("{{{0}}}",100);//{100}

Console.WriteLineConsole.Write方法也有重载支持使用格式字符串。

int a=1,b=2;
Console.WriteLine("{0}+{1}={2}",a,b,a+b);

字符串插值

C#6.0之后,可以在字符串常量前添加$,表明这是一个字符串插值。

在字符串插值中可以使用{表达式:格式}作为占位符,结果会被表达式的字符串形式替换。

int a=1,b=2;
string s1 = $"{a}+{b}={a+b}";
string s2 = $"{3.1415927:f4}";
string s3 = $"{{{100}}}";

字符串插值简化了格式化的使用。

在编译时,编译器会将其转换成对string.Format的调用,对应表达式也会替换成索引。

字符串插值可以和逐字字符串一起使用,字符串插值需要放在前面。

string s = $@"\r{1+1}\n";

字符串相等

字符串使用bool Equals(string other)方法进行相等性比较。

string s1 = "ok";
string s2 = "ok";
Console.WriteLine(s1.Equals(s2));//true

字符串重载了==,!=运行符,因此也可以直接使用运算符进行相等判断。

string s1 = "ok";
string s2 = "ok";
Console.WriteLine(s1 == s2);//true

比较默认是区分大小写的。

如果要支持不区分大小写的比较,使用bool Equals(string other,StringComparison comparison)方法。

string s1 = "ok";
string s2 = "OK";
Console.WriteLine(string.Equals(s1,s2,StringComparison.OrdinalIgnoreCase));//true

字符串比较

字符串使用int Compare(string other)方法进行大小比较,如果返回值为-1,表示自身小,0表示相等,1表示自身大。

string s1 = "a";
string s2 = "b";
Console.WriteLine(s1.Compare(s2)<0);//true

大小比较默认也是不区分大小写的。

使用int Compare(string other,StringComparison comparison)可以进行不区分大小写比较。

string s1 = "a";
string s2 = "B";
Console.WriteLine(s1.Compare(s2,StringComparison.OrdinalIgnoreCase)<0);//true

字符串连接

可以使用Concat静态方法对字符串进行连接。

string s1 = "hello";
string s2 = "world";
string s3 = string.Concat(s1,s2);

Concat的方法的参数可以是任意类型,支持不同数量的重载。内部会调用类型的ToString转换成字符串。

C#对字符串连接提供了特殊支持,可以使用+运算符对字符串进行连接。

string s1 = "hello";
string s2 = "world";
string s3 = s1 + s2;

+ 运算符背后使用的还是Concat.

使用+进行字符串连接只需要有一个操作数是字符串即可,null会被当做空串处理,非null调用ToString

string s1 = "hello " + new object();
string s2 = "hello " + 3.14;
string s3 = "5" + 1;

高效的连接

由于字符串不可变,如果有大量的字符串通过+的方式连接,中间会产生大量临时变量,导致效率低下。

使用System.Text.StringBuilder类可以帮助高效的连接字符串。

StringBuilder b = new StringBuilder();
for(int i=0;i<1000;i++){
    b.AppendLine(b);
}
Console.WriteLine(b.ToString());

通过Append,AppendLine,AppendFormat方法添加新的字符串。

通过ToString方法获取结果。

字符串操作

子串

Substring(int start,int length)`方法。获取字符串的一部分。

查找

bool Contains(string find)方法。判断要查找的字符串是否在当前字符串。

bool StartsWith(string s)方法。判断当前字符串是否以s开头

bool EndsWith(string s)方法。判断当前字符串是否以s结尾

int IndexOf(string find)方法。查找字符串在当前字符串出现的位置,-1表示没找到。

int LastIndexOf(string find)方法。从后向前查找字符串在当前字符串出现的位置,-1表示没找到。

查找方法都有重载支持不区分大小写的查找。

替换

string Replace(string find,string replace)。将当前字符串中出现的一个字符串替换成另一个。

分割

string[] Split(string[] separators,StringSplitOptions option)。将当前字符串按照分隔符进行分隔,可以选择是否保留空字符串。

合并

static string Join(string separator,string[] array)。将字符串数组通过特定的分隔符连接成一个字符串。合并和分割是相反的操作。

格式转换

string ToLowerCase()。将当前字符串转换成小写。

string ToUpperCase()。将当前字符串转换成大写。

清理

string Trim(params char[] chars)。清理当前字符串开头和结尾的字符。

string TrimStart(params char[] chars)。清理当前字符串开头的字符。

string TrimEnd(params char[] chars)。清理当前字符串结尾的字符。

string Remove(int startIndex,int count)。在当前字符串中删除部分字符。

填充

string PaddingLeft(char ch,int totalWidth)。在字符串开头填充特定字符直到符合长度。

string PaddingRight(char ch,int totalWidth)。在字符串结尾填充特定字符直到符合长度。

字符串代理

在.NET中,字符串是以UTF-16的格式存储的。

UTF-16是一种Unicode的传输格式,定义了如何将字符编号表示为字节。

Unicode定义了许多的平面,其中平面0包含了世界上绝大部分文字。

UTF-16使用2个字节表示平面0中的一个文字。

UTF-16在表示平面0之外的文字时,不能使用1个字符来表示,需要使用两个字符,这两个字符称为代理对。

emoji表情是一个典型的不能用一个字符表达的文字。

string s = "😊";
Console.WriteLine(s.Length);//2

微笑表情是一个文字,但是在.NET中,它占用两个字符长度。

如果要精确判断字符串的长度,需要通过Char.IsSurrogate,Char.IsSurrogatePair判断字符是否是代理。

一般情况,大部分常用字符都在平面0,不使用代理。仅作为了解。