今天我们来讲一讲C#语言当中的string
类型,也就是字符串,大家都知道C#是面向对象编程,万物皆对象,string
类型也不列外。string
类型很奇怪,因为它是引用类型,什么是引用类型呢?这里小编就简单说说C#当中值类型和引用类型的区别了。
C#的所有值类型均隐式派生自System.ValueType
:
- 结构体:
struct
(直接派生于System.ValueType
);- 数值类型:
- 整 型:
sbyte(System.SByte的别名),short(System.Int16),int(System.Int32),long(System.Int64),byte(System.Byte),ushort(System.UInt16),uint(System.UInt32),ulong(System.UInt64),char(System.Char);
- 浮点型:
float(System.Single),double(System.Double);
- 用于财务计算的高精度
decimal
型:decimal(System.Decimal)
。
- 整 型:
bool
型:bool
(System.Boolean
的别名);- 用户定义的结构体(派生于
System.ValueType
)。
- 数值类型:
- 枚举:
enum
(派生于System.Enum
); - 可空类型(派生于
System.Nullable<T>
泛型结构体,T
?实际上是System.Nullable<T>
的别名)。
值类型(Value Type
),值类型实例通常分配在线程的堆栈(stack
)上,并且不包含任何指向实例数据的指针,因为变量本身就包含了其实例数据
C#有以下一些引用类型:
- 数组(派生于
System.Array
) - 用户用定义的以下类型:
- 类:
class
(派生于System.Object
); - 接口:
interface
(接口不是一个“东西”,所以不存在派生于何处的问题。主要是接口必须得要别人来实现它,实体类继承了借口,就必须实现接口里面的方法,这一点和抽象类很像,但两者有不同的区别,不要轻易搞混); - 委托:
delegate
(派生于System.Delegate
)。
- 类:
object
(System.Object
的别名);- 字符串:
string
(System.String
的别名)。
简单的来说就是值类型可以存储数值,而引用类型存的是地址;值类型是有系统分配空间在栈上,而引用类型是要由程序员用关键字“new
”来在堆上分配空间的。
大家也看到了string
也是属于引用类型的,接下来我要讲一讲string
这个东西:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
//1、先定义一个字符串
string str = "小编";
//2、给字符串添加另一个字符串
str += "最帅";
//3、打印出来str
Console.WriteLine(str);
}
}
}
输出:
上面就是字符串的添加了,其实大家看到以为是在同一个字符串后面添加了“最帅”两个字,其实不是,而是系统重新分配了个空间,把“小编最帅”这个字符串装了进去,然后让str
变量重新指向新生成的空间地址.
当然C#还有自己一套的处理字符串的API方法,我们先快速介绍下String
类中一些可用的方法。System.String
是一个专门存放字符串的类,允许字符串进行许多操作。由于这种数据类型非常重要,C#提供了它自己的关键字和相关的语法,以便于使用这个类来轻松地处理字符串。
这个类可以完成很多的常见的任务,如替换字符串、删除空白字符串和把字母变成大写形式等。
方法:code | 做用: |
---|---|
Compare | 比较字符串的内容,判断字符串某些字符是否相等 |
Contains | 返回一个值,该值只是指定的子串是否出如今字符串中 |
Remove | 返回指定数量字符在当前这个实例起始点在已删除的指定的位置的新字符串 |
Concat | 把多个字符串实例合并为一个实例 |
CopyTo | 把从选定的下标开始的特定数量的字符复制到数组的一个全新实例中 |
Format | 格式化包含各类值的字符串和如何格式化每一个值的说明符 |
IndexOf | 定位字符串中第一次出现某个给定子字符串或字符的位置 |
IndexOfAny | 定位字符串中第一次出现某个字符或一组字符的位置 |
Insert | 把一个字符串实例插入到另外一个字符串实例的指定索引处 |
Join | 合并字符串数组,建立一个新的字符串 |
LastIndexOf | 与IndexOf同样,但定位最后一次出现的位置 |
LastIndexOfAny | 与IndexOfAny同样,但定位最后一次出现的位置 |
PadLeft | 在字符串的左侧,经过添加指定的重复字符填充字符串 |
PadRight | 早字符串的右侧,经过添加指定的重复字符填充字符串 |
Replace | 用另外一个字符或子字符串替换字符串中给定的字符或子字符串 |
Split | 在出现给定字符的地方,把字符串拆分为一个子字符串数组 |
Substring | 在字符串中检索给定位置的子字符串 |
ToLower | 把字符串转换为小写形式 |
ToUpper | 把字符串转换为大写形式 |
Trim | 删除首尾的空白 |
...... | … |
Replace()
方法以一种智能的方式工作,在某种程度上,它并没有去创建一个新的字符串,除非它实际上要对旧字符串进行某些改变,原来的字符串中包含多个字母,所以在调用一次Replace()
方法就会去分配一个新字符串,因此在执行的过程中需要在堆上创建多个存储字符的字符串对象,最终等待被垃圾收集!显然,如果使用字符串频繁进行文字处理,应用程序会遇到严重的性能问题。为了解决这类问题,系统提供了System.Text.StringBuilder
类。
在使用String
类构造一个字符串时,要给它分配足够的内存来保存字符串,然而,StringBuilder
类通常分配的内存会比它需要的多。我们可以指定StringBuilder
要分配多少内存,如果没有指定,那么默认情况下会根据它实例的字符串长度来确定内存的大小。 StringBuilder
有两个主要的属性:
Length
指定字符串的实际长度Capacity
指定字符串在分配的内存中的最大长度
对字符串的修改就在赋予StringBuilder
实例的内存中进行,这就大大提高了追加子字符串和替换单个字符的效率。
下面我们来介绍下StringBuilder
的声明方法,它的参数是一个初始字符串及该字符串的容量,使用之前记得引用System.Text
程序集
//1、只提供一个字符串
StringBuilder strB1 = new StringBuilder("Hello World!");
//2、用给定的容量来创建一个空的
StringBuilder strB2 = new StringBuilder(20);
//3、可以限定StringBuilder的最大容量
StringBuilder strB3 = new StringBuilder(20, 100);
下面是一些StringBuilder
的常用方法
方法: | 做用: |
---|---|
Append | 给当前字符串追加一个字符串 |
AppendFormat | 追加特定格式的字符串 |
Insert | 在当前字符串中插入一个子字符串 |
Remove | 从当前字符串中删除字符 |
Replace | 在当前字符串中,用某个字符(串)替换另外一个字符(串) |
ToString | 返回强制转换为System.String 对象的字符串 |
下面是StringBuilder
的常用方法的简单使用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
//1、只提供一个字符串
StringBuilder strB1 = new StringBuilder("Hello World!");
strB1.Append("你好,世界");
Console.WriteLine(strB1);
strB1.AppendFormat("钱{0:C}",100);
Console.WriteLine(strB1);
strB1.Insert(2,"0",2);
Console.WriteLine(strB1);
strB1.Remove(2,2);
Console.WriteLine(strB1);
strB1.Replace("Hello","Welcome");
Console.WriteLine(strB1);
strB1.ToString();
Console.WriteLine(strB1);
}
}
}
输出: