C# 字符串定义及常用方法

栏目总目录


一、概念

首先了解下字符的定义:
字符指类字形单位或符号,包括字母、数字、运算符号、标点符号和其他符号,以及一些功能性符号。字符是电子计算机或无线电通信中字母、数字、符号的统称,其是数据结构中最小的数据存取单位,通常由8个二进制位(一个字节)来表示一个字符。

字符是计算机中经常用到的二进制编码形式,也是计算机中最常用到的信息形式。根据计算机的编码方式不同,字符在不同编码方式的存储所占用字节数也不同。字符串,多个字符拼接物。


二、关键性质

不变性:
一般情况下,我们将“一经赋值,其值就不能被更改”视为不变性,字符串的不变性就是指,字符串一经赋值,其值就不能被更改,当通过代码使字符串变量等于一个新的值的时候,堆上会出现一个新的字符串,然后,栈上的变量指向新的字符串,无法更改原来字符串的值


三、String == null或""、String.Empty

1. 空字符串(""和 string.Empty)

  • ""string.Empty 在C#中都表示一个长度为0的字符串,即空字符串。它们在功能上是完全等价的,都指向一个不包含任何字符的字符串对象。
  • 使用 ""string.Empty 初始化字符串变量时,该变量会引用一个在托管堆上分配的空字符串对象。这意味着你可以安全地调用该字符串对象的任何方法或属性,因为确实有一个有效的字符串对象被引用。
  • 在某些情况下,使用 string.Empty 而不是 "" 可以提高代码的可读性,特别是当你想明确表示一个变量应该包含一个空字符串而不是可能未被初始化的 null 时。

2. null 与空字符串的区别

  • 当使用 string str = null; 初始化字符串变量时,str 引用是 null,意味着它不指向托管堆上的任何对象。
  • 尝试访问 null 引用的任何成员(如方法或属性)将导致 NullReferenceException,因为该引用没有指向任何有效的对象。
  • 相比之下,空字符串(“” 或 string.Empty)是一个有效的字符串对象,可以安全地操作而不会引发 NullReferenceException

在C#中,空字符串(“” 和 string.Empty)和 null 在处理字符串时有着本质的区别。空字符串是有效的字符串对象,表示不包含任何字符的字符串,而 null 表示没有引用任何对象。了解这些区别对于编写健壮、易于维护的代码至关重要,因为它可以帮助你避免 NullReferenceException 并确保你的字符串变量在使用前已被正确初始化。


四、StringBuilder

要修改字符串而不是创建新的对象可用,StringBuilder可以自由扩展大小,String分配在栈区,StringBuilder分配在堆区

StringBuilder sb = new StringBuilder(长度);

当指定分配大小之后,性能就会得到提升。在达到容量之前,它不会为其自己重新分配空间。如果超过指定大小系统会当前大小倍增

五、常用方法

一、Object 到 String

  1. ToString()

    object obj = null;
    try
    {
        string str = obj.ToString(); // 如果obj为null,这里会抛出NullReferenceException
    }
    catch (NullReferenceException ex)
    {
        Console.WriteLine("对象为空");
    }
    
  2. obj + “”

    string str = obj?.ToString() ?? ""; // 使用null条件运算符来安全地转换为字符串,如果为null则返回""
    

二、字符串拼接

  1. +

    string str1 = "Hello, ";
    string str2 = "World!";
    string str3 = str1 + str2; // 结果:"Hello, World!"
    
  2. string.Format()

    string str4 = string.Format("{0}, {1}", str1, str2); // 结果:"Hello, , World!"
    
  3. string.Concat()

    string str5 = string.Concat("11", "aa"); // 结果:"11aa"
    

三、判断字符串是否为""、null

  1. 直接比较

    if (str == "" || str == null)
    {
        Console.WriteLine("字符串为空或为null");
    }
    
  2. IsNullOrEmpty()

    if (string.IsNullOrEmpty(str))
    {
        Console.WriteLine("字符串为空或为null");
    }
    
  3. IsNullOrWhiteSpace()

    if (string.IsNullOrWhiteSpace(str))
    {
        Console.WriteLine("字符串为空、为null或仅包含空白字符");
    }
    

四、Substring(),截取字符串

  1. Substring(int startIndex)
    此重载接受一个整数参数 startIndex,它指定子字符串的起始位置(索引从0开始)。从该位置开始,一直截取到原字符串的末尾,返回截取后的子字符串。

    string substr = "Hello, World!".Substring(7); // 结果:"World!"
    
  2. Substring(int startIndex, int length)
    此重载除了接受起始索引 startIndex 外,还接受一个整数参数 length,它指定要截取的子字符串的长度。从指定的起始索引开始,截取指定长度的字符,然后返回这个子字符串。

    string substr2 = "Hello, World!".Substring(7, 5); // 结果:"World"
    

五、Replace(),替换字符串

  1. Replace(Char first, Char second)

    string replaced = "Hello, World!".Replace('l', 'L'); // 结果:"HeLLo, WorLd!"
    
  2. Replace(String firstString, String secondString)

    string replaced2 = "Hello, World!".Replace("World", "C#"); // 结果:"Hello, C#!"
    

六、Split(),字符串转成字符串数组

  1. 使用字符数组作为分隔符
string text = "apple,banana,cherry";
char[] separator = new char[] { ',' };
string[] words = text.Split(separator);
// 结果:["apple", "banana", "cherry"]
  1. 使用字符数组作为分隔符,并限制结果数量
string text = "apple,banana,cherry,date";
char[] separator = new char[] { ',' };
string[] words = text.Split(separator, 3); // 限制为3个子字符串
// 结果:["apple", "banana", "cherry,date"]
  1. 使用字符数组作为分隔符,并移除空字符串
string text = "apple,,banana,cherry,,";
char[] separator = new char[] { ',' };
string[] words = text.Split(separator, StringSplitOptions.RemoveEmptyEntries);
// 结果:["apple", "banana", "cherry"]
  1. 使用字符串数组作为分隔符
string text = "apple-banana|cherry;date";
string[] separator = new string[] { "-", "|", ";" };
string[] words = text.Split(separator, StringSplitOptions.None);
// 结果:["apple", "banana", "cherry", "date"]
  1. 使用字符数组作为分隔符,限制结果数量,并移除空字符串
string text = "apple,,banana,cherry,,date";
char[] separator = new char[] { ',' };
string[] words = text.Split(separator, 4, StringSplitOptions.RemoveEmptyEntries);
// 结果可能取决于实现,但通常会是:["apple", "banana", "cherry", "date"]
// 注意:由于移除了空字符串,所以限制可能不会影响结果
  1. 使用字符串数组作为分隔符,限制结果数量,并移除空字符串
string text = "apple--banana|cherry;;date";
string[] separator = new string[] { "--", "|", ";;" };
string[] words = text.Split(separator, 3, StringSplitOptions.RemoveEmptyEntries);
// 结果:["apple", "banana", "cherry;date"]
// 注意:由于分隔符"--", "|"只分割出3个部分,并且移除了空字符串,所以结果是3个元素

在最后一个示例中,由于分隔符 ";;" 实际上并没有在字符串 "apple--banana|cherry;;date" 中找到匹配项(因为 ";;" 是两个连续的分号,而字符串中只有单个分号作为分隔符的一部分),所以它不会进一步分割字符串。这导致 Split 方法按照给定的限制和选项返回了包含3个元素的数组。此外,当使用 StringSplitOptions.RemoveEmptyEntries 时,任何由连续分隔符产生的空字符串都会被移除,这可能会影响结果数组中的元素数量。

七、Join(),字符串数组转字符串

string result = string.Join(", ", words); // 结果:"Hello, World, C#"

八、ToLower() 、ToUpper(),大小写转换

  1. ToLower() 字符串转成小写

    string lower = "HELLO".ToLower(); // 结果:"hello"
    
  2. ToUpper() 字符串转成大写

    string upper = "hello".ToUpper(); // 结果:"HELLO"
    

九、Trim() 、TrimEnd() 、TrimStart()

  1. Trim() 从当前字符串的开头和结尾删除所有空白字符后剩余的字符串

    string trimmed = "   Hello, World!   ".Trim(); // 结果:"Hello, World!"
    
  2. TrimEnd() 去掉字符串末尾出现的字符或字符数组

    string trimmedEnd = "Hello, World!!!".TrimEnd('!'); // 结果:"Hello, World"
    
  3. TrimStart() 去掉头部出现的字符或字符数组

    string trimmedStart = "   Hello, World!".TrimStart(); // 结果:"Hello, World!"
    // 如果需要去除特定字符,如空格
    string trimmedSpacesStart = "   Hello, World!".TrimStart(' '); // 结果:"Hello, World!"
    

十、判断字符串是否包含指定字符串

  1. Contains() 字符串是否包含指定的字符串

    string str = "Hello, World!";
    bool containsHello = str.Contains("Hello"); // 结果:true
    bool containsCsharp = str.Contains("C#"); // 结果:false
    
  2. IndexOf() 返回指定字符串在字符串中的位置

    int indexHello = str.IndexOf("Hello"); // 结果:0
    int indexCsharp = str.IndexOf("C#"); // 结果:-1,表示未找到
    
  3. StartsWith() 字符串头部是否包含指定字符串

    bool startsWithHello = str.StartsWith("Hello"); // 结果:true
    bool startsWithWorld = str.StartsWith("World"); // 结果:false
    
  4. EndsWith() 字符串末尾是否包含指定字符串

    bool endsWithExclamation = str.EndsWith("!"); // 结果:true
    bool endsWithHello = str.EndsWith("Hello"); // 结果:false
    

十一、字符串比较

  1. Compare()

    string str1 = "apple";
    string str2 = "banana";
    int result = string.Compare(str1, str2); // 结果:< 0,因为"apple"在字典序上小于"banana"
    //按照字典排序比较,当str1 > str2时,返回1;当str1 = str2时,返回0;当str1 < str2时,返回 - 1
    if (result < 0)
    {
        Console.WriteLine(str1 + " comes before " + str2);
    }
    else if (result > 0)
    {
        Console.WriteLine(str1 + " comes after " + str2);
    }
    else
    {
        Console.WriteLine(str1 + " and " + str2 + " are the same");
    }
    
  2. Equals() 比较如果相等就返回true,否则返回false

    bool areEqual = str1.Equals(str2, StringComparison.Ordinal); // 结果:false
    bool areEqualIgnoreCase = str1.Equals(str2, StringComparison.OrdinalIgnoreCase); // 可以比较忽略大小写的版本
    

十二、字符串复制

string original = "abcdefg";
string copied = original.Substring(2, 4); // 从索引2开始,复制4个字符
// 结果:"cdef"

// 如果想要完全复制字符串,可以这样做:
string fullyCopied = original.Substring(0, original.Length);
// 结果:"abcdefg"

十三、字符串插入

使用StringBuilder

StringBuilder sb = new StringBuilder("abc");
sb.Insert(2, "12"); // 在索引2处插入"12"
string result = sb.ToString(); // 结果:"a12bc"

使用字符串连接(不是最高效的方法,特别是对于大量插入操作):

string s = "abc";
string result = s.Substring(0, 2) + "12" + s.Substring(2); // 结果:"a12bc"

六、占位符

1. 字符串插值(String Interpolation)

字符串插值提供了一种非常简洁的方式来嵌入表达式的值到字符串常量中。使用$符号作为字符串的前缀,并使用{}来包含表达式。

int number = 10;
string text = "The number is " + number.ToString(); // 传统方式
string interpolatedText = $"The number is {number}."; // 字符串插值

2. String.Format 方法

String.Format方法提供了一种使用占位符和对应参数来格式化字符串的方式。占位符是由大括号{}包围的数字(表示参数的索引)或命名占位符(C# 6.0起支持)。

int number = 10;
string formattedText = String.Format("The number is {0}.", number); // 使用索引

// C# 6.0+ 支持命名占位符
string name = "Alice";
string namedFormattedText = String.Format("Hello, {name}!", name); // 注意:实际使用时,这需要自定义格式化提供程序或修改代码为String.Format("Hello, {0}!", name)
// 更推荐使用字符串插值
string namedInterpolatedText = $"Hello, {name}!";

注意:直接在String.Format中使用命名占位符(如{name})是不支持的,除非你使用了自定义的格式化提供程序或者简单地使用索引(如上例中的{0})。对于命名占位符的支持,在字符串插值中更为直接和方便。

3. 复合格式化

String.Format方法还支持复合格式化,允许你更精细地控制数字、日期和时间的格式。

double pi = 3.14159265358979;
string piFormatted = String.Format("Pi is approximately {0:N2}.", pi); // 使用复合格式化指定小数点后两位

七、字符串分解案列

需求:按照JSON文件对比机器命令id返回结果,把机器错误信息转义成中文,即数组里的数字,难点,数组里包含了个小数组,开头结尾不要
错误格式如:
0,{[[-2,3],[],[0],[],[],[21120],[21120]]},GetErrorID();
0,{[[85],[],[],[],[],[]]},GetErrorID();
但是没有错时,返回0,{[[],[],[],[],[],[]]},GetErrorID(); ,
会出现少掉前面那个数组,第一个数组为一类,其余为另一类

private string CauseShow(string id)
		{
			try
			{
				string[] s1 = id.Split(new char[] { '{', '}' }, StringSplitOptions.None);
				string[] s2 = s1[1].Split(new char[] { ',' }, StringSplitOptions.None);
				int Length = s2.Length;
				string controllerStr = null;
				string EndStr = null;
				if (Length == 6)
				{
					for (int i = Length - 1; i > Length - 6; i--)
					{
						if ((i == Length - 1 && s2[Length - 1].Length > 3) || (s2[i].Length > 2 && !(i == Length - 1)))
						{
							string[] s = s2[i].Split(new char[] { '[', ']' }, StringSplitOptions.None);
							string ss = null;
							for (int j = 0; j < alarm_servo.Length; j++)
							{
								if (Convert.ToInt32(s[1].ToString()) == alarm_servo[j].id)
								{
									ss = alarm_servo[j].Zh_CN.description;
								}
							}
							s2[i] = ss;
						}


						if (s2[i].Length == 2 || (s2[i].Length == 3 && i == Length - 1))
						{
							s2[i] = "";
						}
						if (i <= 0)
						{
							break;
						}
					}
					string[] s3 = s1[1].Split(new char[] { ',', '[', ']' }, StringSplitOptions.None);
					ArrayList s3List = new ArrayList();
					for (int i = 2; i < s3.Length - 2; i++)
					{
						if (s3[i] != "")
						{
							s3List.Add(s3[i]);
						}
						else
						{
							break;
						}
					}
					if (s3List.Count > 0)
					{
						for (int i = 0; i < s3List.Count; i++)
						{
							for (int j = 0; j < alarm_controller.Length; j++)
							{
								if (Convert.ToInt32(s3List[i].ToString()) == alarm_controller[j].id)
								{

									controllerStr += alarm_controller[j].Zh_CN.description;
									if (!(i == s3List.Count - 1))
									{
										controllerStr += ",";
									}
								}

							}
						}
					}

					for (int i = Length - 1; i > Length - 5; i--)
					{
						if (s2[i] == "")
						{
							continue;
						}
						else
						{
							EndStr += s2[i] + ",";
						}
					}
				}
				else
				{
					for (int i = Length - 1; i > Length - 6; i--)
					{

						if ((i == Length - 1 && s2[Length - 1].Length > 3) || (s2[i].Length > 2 && !(i == Length - 1)))
						{
							string[] s = s2[i].Split(new char[] { '[', ']' }, StringSplitOptions.None);
							string ss = null;
							for (int j = 0; j < alarm_servo.Length; j++)
							{
								if (Convert.ToInt32(s[1].ToString()) == alarm_servo[j].id)
								{
									ss = alarm_servo[j].Zh_CN.description;
								}
							}
							s2[i] = ss;
						}

						if (s2[i].Length == 2 || (s2[i].Length == 3 && i == Length - 1))
						{
							s2[i] = "";
						}
						if (i <= 0)
						{
							break;
						}
					}
					string[] s3 = s1[1].Split(new char[] { ',', '[', ']' }, StringSplitOptions.None);
					ArrayList s3List = new ArrayList();
					for (int i = 2; i < s3.Length - 2; i++)
					{
						if (s3[i] != "")
						{
							s3List.Add(s3[i]);
						}
						else
						{
							break;
						}
					}
					if (s3List.Count > 0)
					{
						for (int i = 0; i < s3List.Count; i++)
						{
							for (int j = 0; j < alarm_controller.Length; j++)
							{
								if (Convert.ToInt32(s3List[i].ToString()) == alarm_controller[j].id)
								{

									controllerStr += alarm_controller[j].Zh_CN.description;
									if (!(i == s3List.Count - 1))
									{
										controllerStr += ",";
									}
								}

							}
						}
					}


					for (int i = Length - 1; i > Length - 5; i--)
					{
						if (s2[i] == "")
						{
							continue;
						}
						else
						{
							EndStr += s2[i] + ",";
						}
					}
				}
			}
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

語衣

感谢大哥

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值