一、分清楚值类型与引用类型
正确理解值类型与引用类型,可以更好的帮助软件开发人员写出性能更好且正确稳定运行的程序:
区别 | 值类型 | 引用类型 |
定义 | 所有继承自【System.ValueType】类型的都是值类型(valueType继承自System.Object),如常见基础数据类型【byte,short,int,long,float,double,decimal,char,bool 、enum和 struct】都是值类型 | 所有不继承 【System.ValueType】类型都都是引用类型;对于C#而言所有以【Class】关键字定义的内容都是引用类型;【string、class】都是引用类型 |
变量赋值 | 值类型的变量赋值是直接获取到一个真实数据副本 ;变量与数据是【一对一的关系】互不影响 | 引用类型赋值只是把对象的引用赋给变量; 变量与数据对象是【多对一的关系】相互影响 |
内存分配 | 【值类型】变量声明后,不管是否已经赋值,编译器为其在【线程栈】分配【静态内存】,【栈内分配空间大小因变量类型而异】 线程栈的空间相对有限,但运行效率比堆高的多 | 【引用类型】声明一个类时,只在线程栈中分配一小片内存空间用于容纳一个数据对象地址,且此时没有为其分配堆上的数据对象内存空间;只有使用 new 关键字创建一个类的实例时,才会分配堆上的空间,并把堆上空间的地址保存到线程栈上分配的小片空间中 |
继承结构 | 【值类型】都继承自【System.ValueType】,它们的比较方法【ValueType.Equals(Object)】实现了【数据内容的比较】 | 【引用类型】都继承自【System.Object】,它们的比较方法【Object.Equals(Object)】实现的是【引用相等性;等效于调用 Object.ReferenceEquals】 System.Object.Equals 方法 - .NET | Microsoft Learn |
使用场景 | 【值类型】在内存管理方面具有更好的效率,并且不支持多态,【适合用做存储数据的载体】 判断使用值类型依据: ①只用于数据存储; ②永远不可能有子类; ③没有多态行为; | 【引用类型】支持多态,【适合用于定义应用程序的行为】 C#面向对象的三大特性(封装、继承、多态) |
C#的两种类据类型:值类型和引用类型_c# .value2-CSDN博客文章浏览阅读4.7k次,点赞5次,收藏18次。一、什么是值类型,什么是引用类型概念:值类型直接存储其值,而引用类型存储对其值的引用。部署:托管堆上部署了所有引用类型。引用类型:基类为Objcet值类型:均隐式派生自System.ValueType:值类型:byte,short,int,long,float,double,decimal,char,bool 和 struct 统称为值类型。..._c# .value2https://blog.csdn.net/xiaochenXIHUA/article/details/90202915
二、String与StringBuilder都是类属于引用类型
2.1、String类
字符串是用于表示文本字符的顺序集合(即:string或String是表示System.Char字符的顺序集合,且该顺序集合的值是只读的,不可改变,这意味着只要对string对象的每个操作都会创建新的字符串对象,若涉及大量修改则会在内存中存在大量的字符串对象,占用很多内存【字符串可以包含字母、数字或其他符号,在C#中使用英文双引号将字符集合包起来就产生了字符串】);在内存中一个String类对象的字符串最多容纳10亿个字符,大约2GB的空间;
String 类 (System) | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/api/system.string?view=net-9.0
2.1.1、string与String
在C#中,string与String没有区别,string是String的一个别名;而String是Sytem命名空间下的一个类;
string str = "测试字符串";
String strS = "测试字符串";
Console.WriteLine($"string内容是【{str}】___String内容是【{strS}】");
2.1.2、实例化string对象
1、给字符串文本string分配变量
public static void TestStrObj()
{
string str = "测试字符串";
String strS = "测试字符串";
Console.WriteLine($"string内容是【{str}】___String内容是【{strS}】");
string str10 = "ABCDaaddfshafs";
Console.WriteLine(str10);
string str11 = "1234567890";
Console.WriteLine(str11);
string str12 = "~!@#$%^&*()";
Console.WriteLine(str12);
string str2 = "路径:C:\\Users\\Public\\Pictures";
Console.WriteLine(str2);
string str3 = @"C:\Users\Public\Pictures";
Console.WriteLine(str3);
}
2、调用String类的构造函数
String 构造函数 (System) | Microsoft Learn
public static void TestStrObj()
{
//将字符数组转为字符串
char[] charArray = {'H','e','l','l','o',' ','W','o','r','l','d' };
string stra = new string(charArray);
Console.WriteLine(stra);
//创建重复字符的字符串
string strr = new string('H',9);
Console.WriteLine(strr);
}
3、通过字符串串联运算符+
public static void TestStrObj()
{
string name = "字符串";
int num = 3;
string str = "拼接字符串" + "【你好】" + "CoffeeMilk";
Console.WriteLine(str);
string str2 = "当前是:" + DateTime.Now.ToString();
Console.WriteLine(str2);
string str3 = $"测试【{name}】【{num}】";
Console.WriteLine(str3);
}
4、通过格式化方法转为字符串
public static void TestStrObj()
{
string name = "字符串";
int num = 3;
string str = string.Format("这是一个关于{0}格式化的{1}测试", name, num);
Console.WriteLine(str);
}
5、通过检索属性方法
public static void TestStrObj()
{
string str = "Today china technology is quilk develop";
int startIndex = str.IndexOf(' ') + 1;
string newstr = str.Substring(startIndex,5);
Console.WriteLine(newstr);
string[] strArray = str.Split(' ');
string newstr2 = strArray[1];
Console.WriteLine(newstr2);
}
2.1.3、string的适用场景
1、对字符串所做的更改数较小; 此时StringBuilder 可能会提供微不足道或没有性能改进 String。
2、执行固定数量的串联操作时,尤其是字符串文本。 在这种情况下,编译器可以将串联操作合并为单个操作;
3、在生成字符串时必须执行广泛的搜索操作。 类 StringBuilder 缺少搜索方法,例如 IndexOf
或 StartsWith
。 你必须将 StringBuilder 对象转换为这些操作的对象 String ,这可以抵消使用 StringBuilder的性能优势。
2.2、StringBuilder类
StringBuilder类表示可变字符(char)集合的字符串;这意味着可以直接修改该对象的值(可以通过附加、删除、插入或替换来修改),而不用每次在修改时在内存创建新的对象。其所占的空间会随着内容的增加而自动扩充。
StringBuilder 类 (System.Text) | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/api/system.text.stringbuilder?view=net-9.0
2.2.1、StringBuilder的实例化与操作
使用 .NET 中的 StringBuilder 类 - .NET | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/standard/base-types/stringbuilder
如下展示了如何实例化 StringBuilder 类型的对象,及如何对StringBuilder对象执行各种操作(追加、插入、替换、移除)。
需要注意的是StringBuilder的ToString()方法返回的是String类对象。
public static void TestStrigBuilder()
{
//创建一个StringBuilder的对象,且预期可容纳64个字符
StringBuilder sb = new StringBuilder("这是一个测试",16);
//直接在该字符串末尾添加新的字符
sb.Append(new char[] {'A','B','C' });
//添加格式化的字符串
sb.AppendFormat("很高兴认识你{0}{1}","Coffee","Milk");
//显示当前的字符串及其长度
Console.WriteLine($"【{sb.ToString()}】长度是【{sb.Length}】");
//给字符串的指定位置插入内容
sb.Insert(4,"【StringBuilder类】");
//替换
sb.Replace("测试", "操作");
Console.WriteLine($"【{sb.ToString()}】长度是【{sb.Length}】");
sb.Remove(sb.Length-4,4);
Console.WriteLine($"【{sb.ToString()}】长度是【{sb.Length}】");
}
概述:如何在 .NET 中设置数字、日期、枚举和其他类型的格式 - .NET | Microsoft Learnhttps://learn.microsoft.com/zh-cn/dotnet/standard/base-types/formatting-types#default-formatting-using-the-tostring-method
2.2.2、StringBuilder的适用场景
1、当你期望代码在设计时对字符串进行未知数量的更改(如:使用循环中多次对字符串修改);
2、你期望对字符串内容进行大量的更改操作;
2.3、String类与StringBuilder类的区别
特性 | String类 | StringBuilder类 |
可变性 | 不可变 (一旦创建了String类字符串,字符串内容就不可更改;每次涉及到该字符串的更改【追加、替换、删除等所有操作】都会生成一个新的字符串对象;原字符串内容不变) | 可变 (创建了StringBuilder对象后,每次对该对象的字符串内容进行各种更改【追加、替换、删除等所有操作】而不会生成新的对象;非常适合频繁更改字符串内容的场景) |
性能 | 对字符串大量操作会创建大量新字符串对象,浪费内存;导致性能较低 | 对字符串大量操作也只会对当前对象内操作,不会创建新对象,内存消耗较少,性能较高 |
适用场景 | ①对字符串所做的更改数较小; ②操作固定数量字符串文本串联; ③在生成字符串时必须执行广泛的搜索操作 | ①你期望代码在设计时对字符串进行未知数量的更改; ②你需要对字符串内容进行频繁修改操作; |
三、其他学习资料
StringBuilder与String互转 - 盟约 - 博客园https://www.cnblogs.com/huameitang/p/10528646.html
C#中的字符串, String类和StringBuilder类-腾讯云开发者社区-腾讯云https://cloud.tencent.com/developer/article/1861078如何提高C# StringBuilder的性能_51CTO博客_c# stringbuilder
https://blog.51cto.com/u_14995043/4627471C# String与StringBuilder - 苍 - 博客园
https://www.cnblogs.com/cang12138/p/7323709.htmlC# StringBuilder & String vs StringBuilder (with Performance Comparison) in C# .NET | Pro Code Guide
https://procodeguide.com/csharp/string-vs-stringbuilder-csharp/