C#语言系列讲座(13)-字符串

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情
字符串

字符串在C#中是System.String(或简化为小写string)类的一个实例,它表示一个不变的字符序列。字符串创建的语法很简单:string s =“C# Sharp XP”, 即在托管堆上创建了内容为字符串“C# Sharp XP”的内存区域,而s仅仅是指向该内存区域的一个引用句柄。

看下面的代码:
string s1=“Hello,World!”;
string s2=s1;


这时,s1和s2都指向同一块含“Hello,World!”的内存区。

C#为字符串提供了两种转义表达。第一种和传统C/C++中的转义字符表达相同,即用反斜线“/”加特定字符的表达方式。如“/t”表示Tab键,“/r”表示回车,“/n”表示换行等等。要表示C盘“我的文档”下的一个文件路径:string MyPath=“C://Documents and Settings//Cornfield//My Documents//MyFile.cs”,其中双斜线被转义为单斜线。而采用第二种表示方法,可以在字符串前加一个“@”符号,这样就可按正常的字符序列来表达字符串,如上面的文件路径可以像这样来表达:string MyPath=@“C:/Documents and Settings/Cornfield/My Documents/MyFile.cs”,和前面的表达效果相同。第二种表示方法在我们表达包含特殊字符的长字符串的情况下非常有用,它甚至能够表达不能显示为字符形式的回车、换行等特殊字符。

可以通过索引器来获取字符串中的单个字符(16位Unicode编码)——这和C/C++中的字符串数组在本质上是完全不同的。下面的代码演示了这一点:
string s =“C# Sharp XP”;
for (int index = 0; index < s.Length; index++)
Console.WriteLine(s[index]);


由于字符串恒定性的缘故,我们不能做类似s[index]=‘p’的改变,这是由System.String的只读索引器public char this[int index] {get;}来保证的。

作为System.String类型的实例,系统为字符串提供了丰富多样的操作,这里只对几个比较特殊的方法做一剖析。String类实现了ICloneable接口,但String.Clone方法并不是返回一个新创建的String实例,而是仅仅返回一个和参数一样的引用句柄,也就是说“string s2=s1.Clone()”和前面的“string s2=s1”效果一样。需要返回一个和参数内容一样,但引用句柄不同的字符串可以采用静态的String.Copy方法。实例方法System.Equal和类操作符“public static bool operator ==(string a,string b);”比较的都是两个字符串的内容是否相等,而非引用句柄。

下面的代码示例,集中展示了上述方法的行为:
using System;
class Test
{
public static void Main()
{ string s1=“Hello,World!”;
string s2=s1.Clone().ToString();
//克隆,句柄相等,内容相等
string s3 = string.Copy(s1);
// 拷贝,句柄不等,内容相等
Console.WriteLine(s1==s2);
//True,内容相等
Console.WriteLine(s1==s3);
//True,内容相等
Console.WriteLine((object)s1==(object)s2);
//True,句柄引用相等
Console.WriteLine((object)s1==(object)s3);
//False,句柄引用不等
}
}


字符串恒定性

字符串的恒定意思是指一旦字符串的值(System.String实例)被创建后,它便不可以改变。

看下面一段典型的代码:
string s1=“Hello,”;
string s2=“World!”;
s1+=s2;


上面的语句执行完后,s1为“Hello,World!”,s2为“World!”。但s1原来的值“Hello”并没有因此消失,确切地讲“Hello”仍然占有内存空间,只不过现在不能被我们引用到而已,它只能等待.NET的自动垃圾收集器来回收其资源,这在以前的C++中就造成了内存泄漏,也就是说在上面的语句执行后,我们将拥有“Hello,World!”(s1引用句柄指向的值),“World!”(s2引用句柄指向的值),“Hello,”(没有引用句柄指向该值)共三个存储字符串的内存区。

字符串值恒定的特征还表现在作为string类型的参数传递上,我们看下面的例子:
using System;
class Test
{
public static void Main()
{
string p=“Hello,”;
MyMethod(p);
Console.WriteLine(p);//输出“Hello,”
}
public static void MyMethod(string p)
{
p+=“World!”;
Console.WriteLine(p);//输出Hello,World!
}
}


虽然说string类型在C#中是一种引用类型,但由于字符串的恒定性质,方法MyMethod并没有改变传进来的p的引用句柄(若要改变则需要采用ref关键字修饰参数),而这个引用句柄本身指向的表达字符串“Hello,”的内存区域也没有改变,自然通过MyMethod方法的调用字符串p也就不会改变。

理解字符串值恒定的特征对我们在C#中熟练操作字符串非常重要,比如System.String类的很多方法实际上并没有改变参与操作的字符串本身,而是创建一个新值,仅仅把原来的字符串留给自动垃圾收集器。如果C#程序中频繁地操作字符串,很有可能引起字符串大量的“创建/丢弃”动作,势必给系统造成负担,这时我们应该借助于StringBuilder类。StringBuilder位于System.Text命名空间下,它的实例不是字符串,但它为可变字符串提供了丰富的操作: 插入,追加,替换,删除等,同时由于它的操作发生在同一块内存区,因此没有恒定字符串System.String频繁地“创建/丢弃”的消耗,可以非常方便地利用构造器“public StringBuilder(string value);”来创建含有value字符串值的StringBuilder类实例,同样可以用StringBuilder的实例方法ToString非常方便地得到类型为string的字符串的内容。和System.String类的很多方法相反,StringBuilder类的方法改变的正是参与操作的StringBuilder类实例本身,并不创建新值!

作为一个一般性的原则,如果仅仅涉及到字符串的内容表示或者创建新的字符串,往往采用System.String的方法就可以了,但如果涉及到大量的字符串内容的变更操作时,就很有必要采用StringBuilder类的一些相关方法,然后再调用ToString方法得到我们需要的字符串。
Unity零基础到进阶 | UGUI对象从创建到屏幕渲染完整流程 UGUI核心要点:脏标记驱动、分阶段重建(Layout→Graphic)、C#生成顶点数据,C++ Canvas做合批Batch,最后提交GPU 时间轴顺序:对象实例化 → Awake/OnEnable → 标记Dirty入队列 → Update执行游戏逻辑 → willRenderCanvases触发重建(Layout重建→裁剪→Graphic图形重建)→ C++ Canvas BuildBatch合批 → 提交GPU → 屏幕显示 阅读详情

相关推荐

C# AutoCAD 二次开发中的事务(Transaction)深度剖析:从基础原理到高级应用

本文深度剖析C# AutoCAD二次开发中的事务机制,强调其在保障原子性、线程安全与资源管理中的核心作用。重点阐述“黄金法则”——必须使用using语句管理事务,避免忘记提交或未结束事务的常见错误。深入讲解打开模式、对象升级降级、嵌套事务及事务组的应用,揭示性能陷阱与高级控制策略。强调事务仅在主线程中有效,杜绝后台线程操作,确保插件稳定高效。

ultramand的博客,重生之我在cad上二次开发猛猛敲C#代码~ 34

Statements without Semicolons

一条物理行 = 多条语句,完全合法;对比:Python 靠缩进和换行区分语句,C# 完全靠分号,这就是 “free-form 语言” 的特征。同样地,有些情况 —— 例如 using 声明 —— 虽然带有分号作为后缀,但它并不是一条语句。例如,代码清单 1.3 在一行里包含两条语句,两者结合,分别在两行中显示 Up 和 Down。由于换行并不分隔语句,你可以把多条语句写在同一行,C# 编译器会把这行解释为包含多条指令。实际上,代码块本身也被视为语句(代码块同样由语句组成),而且它们不需要以分号结尾。

龙山大佛爷的博客 150

C# .NET 周刊 |2026 年 8 月 4 期

本文介绍了用 C#、WinForm、WebView2、HTML 和 CSS 构建管理系统界面的方案。它强调用 WebView2 连接原生窗体和网页界面,实现数据传递、事件通知和样式切换,适合用户、权限、日志、报表等常见后台场景。方案思路清晰,实用性较强,但技术深度和原创细节一般,缺少实现代码和性能分析。

InCerry的博客 265

外贸独立站SEO优化全攻略:从0到1的完整指南

外贸独立站SEO是低成本获取精准海外流量的关键。本文系统梳理完整优化框架:从关键词研究(核心词与长尾词筛选)、站内优化(标题/URL/内链)、技术优化(HTTPS/速度/移动端/结构化数据),到内容营销、外链建设及本地化多语言策略,并涵盖数据监测与持续优化,助你建立系统化SEO知识体系。

2601_96764108的博客 276

Lua 基础语法(六)xLua Lua 调用 C# 交互

Lua通过cs.前缀访问C#类、对象与组件,使用冒号调用实例方法,点号调用静态成员。创建对象无需new,可直接调用类名;支持ref/out多返回值、params可变参数及委托事件订阅。注意重载函数因Lua统一为number类型,可能受桥接注册顺序影响。底层依赖虚拟栈与Gen桥接文件实现跨语言交互,需手动生成并注入代码。关键点包括命名空间前缀、:与.区分、事件注册移除、虚拟栈原理及热更新机制。

2301_80252792的博客 393

C# UdpClient 单播 三种通信版本

UDP单播:一对一精准通信,数据只能发送给指定唯一IP+端口的设备,点对点专属数据交互。手动自定义本机IP、本机绑定端口手动输入对方IP端口,可与任意UDP设备通信通用性最强,适配所有UDP点对点通信场景。

2401_84677775的博客 301

基于 C# / .NET 8 + Windows Forms + SQLite 的桌面银行业务演示系统——华夏示范银行管理系统

华夏示范银行管理系统是一款基于C#/.NET8+WindowsForms+SQLite的桌面端业务演示系统,采用分层架构设计,支持超级管理员、管理员与客户三类角色。系统集成登录认证、顶部导航、客户/产品管理、持仓价值计算、操作日志双写(SQLite+文本)、空闲自动登出及数据导出功能。通过“内容控件+按钮栏”组合模式实现页面动态扩展,支持自定义页配置与灵活功能开关,具备高可维护性与可拓展性,适用于银行业务流程教学与原型验证。

weixin_66547608的博客 150

Lua 基础语法(七)xLua 完整热更新 Demo

本文详解xLua Hotfix热更新技术,涵盖[Hotfix]标签作用与性能风险、AB包打包配置、UnityWebRequest异步下载及进度条实现、自定义AddLoader加载器注册、Lua热修复C#方法流程,并通过完整Demo演示从点击生成Cube到热更为红色Sphere的全过程。重点解析同名资源踩坑、Hotfix注入失效、重载函数调用异常等高频问题,对比xLua与下一代Huatuo(HybridCLR)热更新方案,强调其能力边界与选型建议,助力开发者掌握热更新核心技能并落地实战。

2301_80252792的博客 358

C# 图像使用AVX2指令集:使用OpenCvSharp实现字节图像解压缩速度和map_image算子速度提升

C# 图像使用AVX2指令集:使用OpenCvSharp实现字节图像解压缩速度和map_image算子速度提升

xianzuzhicai的博客 256

手写观察者模式:C#上位机状态通知的优雅解法

定义:定义对象间一种一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都会收到通知并自动更新。两个核心角色:角色别名职责Subject​主题 / 被观察者 / 发布者维护观察者列表,提供注册/注销,状态变化时通知Observer​观察者 / 订阅者定义接收通知的接口(Update 方法)注册(Attach)→ 变化 → 通知(Notify)。观察者模式的本质,是把"谁关心我变了"这个问题,从「编译期硬编码」变成「运行期动态注册」。简单场景用event(语言级、够用);

A_nanda的博客 455

Lua 基础语法(四)C# 原生交互(LuaInterface)

LuaInterface是C#与Lua互调桥梁,含两个dll,已停维护但适合理解热更新原理。C#通过LuaEnv执行Lua字符串或文件,读取变量、调用函数、遍历表;Lua可用LuaNet加载C#程序集,访问实例(冒号)与静态成员(点号)。热更新核心:仅替换Lua脚本,C#无需重编译。

2301_80252792的博客 303

c#软件开发学习笔记--WPF(MVVM框架)

概念:区域(Region)是 Prism 中用来「动态容纳视图」的占位容器,替代传统<Frame>。你负责把视图放进去,展示的位置由区域决定。定义方式:在 XAML 中用附加属性prism:RegionManager.RegionName="区域名"标记某控件为区域(常用于):打开方式(两种)视图注入(固定投放)——启动时直接把视图放进来,之后不切换:_m = m;_m = m;

Z599817841的博客 341

Unity · 性能优化:内存管理完全指南:从托管堆到跨桥开销

在 Unity 中,托管内存(C# 对象)与本机内存(引擎对象) 之间存在频繁的数据交换。这种跨越两个内存域的操作,被称为“跨桥”(Crossing the Bridge)。本机部分:场景中的 GameObject、Transform、Mesh、Texture 等,其核心数据存储在本机内存中。托管部分:我们在 C# 中持有的引用(如 Transform变量),实际上是一个托管包装器(Wrapper),它指向本机对象,但自身只占很少的内存。

gghhb12的博客 348

学习C#开源报表组件Seal Report(26:Seal Report Designer界面布局-22)

学习Seal Report Designer软件左侧面板的Views节点中Model View控件的属性用途

gc_2299的博客 190

数据结构-前缀树(Trie)

【代码】数据结构-前缀树(Trie)

SeanDragon的博客 213

Lua 基础语法(八) Unity Huatuo (HybridCLR)

HybridCLR是基于IL2CPP的Unity原生C#热更新框架,支持AOT编译,性能高、内存低,兼容泛型、反射等全语法,无需学习Lua。通过AssemblyDefine划分热更程序集,打包产出独立dll,运行时加载并反射调用。相比xLua需打标签、ILRuntime受限于iOS禁用JIT,HybridCLR可新增类与方法,支持完整热更新。需Unity 2019.4+,配置IL2CPP后端,热更dll需改后缀为.bytes并置于StreamingAssets,宿主加载后执行逻辑。

2301_80252792的博客 444

基于C#实现(WinForm)文件管理系统

本项目主要使用了两种主要的数据结构。首先是C# WinForm所内置的TreeView树结构,主要用来实现项目的目录树。另一种是自定义的森林结构,用来存放文件系统中的所有文件夹和文本文件,以及它们之间的对应关系。以下是自定义结点的部分定义。//左孩子//右兄弟//父结点//当前结点的信息左侧为文件系统目录结构树,以树型结构展示出了所有的文件夹以及文本文件。右侧是一些选项栏,可以进行格式化、新建文件夹等操作,同时可以看到程序目前的总块数和已用块数、

神仙别闹的自留地 178

微软技术周报 2026-08-31~09-07:GPT-6 Astra 登陆 Foundry、M365 全球认证故障复盘、C# 15 封闭层级

本期聚焦技术动态,不含财务信息。信息来源:Microsoft Learn、.NET News Daily、Azure Weekly(Issue 578)、Microsoft Security Blog、MSRC、Pureinfotech、9to5Windows、Neowin、BleepingComputer、InfoQ 中文、cnBeta、快科技、Microsoft 365 Message Center 等中英文媒体与官方渠道。

海盗Sharp的博客 427

Elasticsearch ES|QL:让全文本搜索无处不在

Elasticsearch 9.5引入MATCH与TO_TEXT组合技:TO_TEXT将任意字符串转为text类型,MATCH对运行时值进行真正的分词匹配,无需预建倒排索引。它支持未映射字段、keyword临时全文搜索、跨索引类型不一致等场景,替代LIKE/RLIKE的字符级匹配,实现大小写不敏感、词边界及词干处理,提升搜索语义准确性。

海兰 376
上一篇: 用C#创建COM对象
下一篇: c#语言系列讲座(14) 结 构
Ninth
博客等级 码龄22年 4粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值