C# String 类型:那些你可能不知道的秘密

news2024/11/24 9:32:16

Coding-97

前言

嗨,大家好!

今天咱们来聊一聊一个看似简单却充满玄机的话题 —— String 类型。

字符串应该是所有编程语言中使用最频繁的一种基础数据类型。

在 C# 中,String 可谓是特别的存在:它是引用类型,存储在托管堆中,但在应用上,它却表现得像是值类型。

这个看似简单的类型,背后可藏着许多小秘密呢!准备好一探究竟了吗?

几个问题

作为一名 .NET 程序员,你一定和 String 打过不少交道,在正式分享之前,咱们来做个小测验,考考你的 String 知识,看看你对这个常用类型了解多少:

  1. 下面这行代码一共创建了几个字符串对象?为什么?

    String str = new String("abc")
  2. 下面两行代码,哪个性能高?为什么?

    string str1 = "str1" + 9;
    string str2 = "str2" + 9.ToString();
    
  3. 在下面这两种字符串拼接方式中,哪一种效率更高?为什么?

    static void test1()
    {
        string a = "t";
        a += "e";
        a += "s";
        a += "t";
    }
    
    static void test2()
    {
    	
        string a = "t";
        string b = "e";
        string c = "s";
        string d = "t";
        string result = a + b + c + d;
    }
    

能回答上来吗?不能也没关系,跟我继续往下看吧!

创建 String 的 6 种方式

在 C# 中创建字符串其实挺简单的,但不同的创建方式背后有着不同的性能影响。

下面是 6 种常用的创建方法,看看你熟悉哪些!

  1. 字面量创建

    string str = "Hello, World!";
    

    评价:这是最常见也是最简单的方式,直接用双引号包起来就是字符串,你不需要做额外的操作,简单直接!

  2. 使用 new 关键字

    String str = new String("Hello, World!");
    

    评价:理论上你可以使用 new 来创建字符串对象,但这样做并不推荐,除非你有特殊的理由,因为字符串是不可变的,这样做至少会创建 2 个字符串对象,反而带来额外的性能开销

  3. 字符数组拼接

    char[] chars = { 'H', 'e', 'l', 'l', 'o' };
    string str = new string(chars);
    

    评价:这个方法在实际使用中不太常见,了解一下就好,但却能让你明白字符串的本质其实是一个字符数组

  4. 字符串拼接

    string name = "World";
    string str = "Hello" + ", " + name + "!";
    

    评价:使用加号(+)来拼接字符串,这是另一种常见的创建方式,但在循环中这样做可能会导致性能问题,因为它每次都会创建一个新的字符串对象,适合偶尔使用,频繁使用建议换成 StringBuilder。除此之外,在拼接要警惕装箱操作带来的额外性能开销。

  5. 格式化字符串

    string str = string.Format("Hello, {0}!", name);
    

    评价:严格地讲,这也是字符串拼接的一种方式,通过 string.Format() 方法,你可以动态插入变量并格式化输出字符串,更加灵活,性能也更高。

  6. 插值字符串

    string str = $"Hello, {name}!";
    

    评价:C# 6.0 推出的语法糖,可以直接在字符串内部嵌入变量,语法更加简洁优雅。

String 的本质

什么是 String 呢?

本质上,String 就是一连串的有顺序的 16 位的字符数组,简单地说,就是 char[],所以它也具备数组的一系列特性。

String 的特殊性

String 在使用上太频繁了,所以在实现机制上,CLR 给了它很多特殊的照顾:

  1. 类型处理特殊

    String 类型是引用类型,存储在托管堆中,但在应用上,String 类型表现为值类型。

  2. 不可变性

    一旦创建了一个字符串对象,你就不能改变它的内容。
    这意味着每次你 “修改” 一个字符串时,实际上是在创建一个新的字符串对象。
    这个特性保证了字符串的线程安全性和数据完整性。

  3. 字符串池

    C# 中有一个叫做字符串池的东西,它会自动管理字符串对象。
    如果你创建了一个字符串,而这个字符串已经在池中存在了,那么它就不会再创建一个新的对象,而是直接引用已有的对象。这样可以节省内存空间,提高性能。

  4. 字符编码

    String 默认使用 UTF-16 编码,这让它能够存储丰富的字符集,包括中文、符号等,便于程序国际化。

如何 “销毁” String?

可以用以下语句来手动 “销毁” String 吗?

string testStr = "Hello, String!";
testStr = null;

答案是不可以,因为字符串是不可变的,也就是说一旦创建,它的内容就不能被更改,当你对字符串进行修改时,实际上是创建了一个新字符串,所以它并不能被手动 “销毁”。

和其它引用类型一样,当没有任何引用指向一个字符串对象时,垃圾回收器(GC)会在适当的时候回收它占用的内存。

也就是说,字符串的生命周期由引用它的对象来决定。

使用建议

  1. 尽量使用字面量创建

    这通常是最简洁和高效的。

  2. 避免频繁拼接

    在循环或大量拼接操作中,尽量避免使用 + 来拼接字符串,改用 StringBuilder 提高性能。

  3. 利用字符串池

    如果你知道字符串的内容不会改变,可以使用 string.Intern() 方法来尝试获取字符串池中的引用,这样可以提高性能。

  4. 字符串比较

    在比较字符串时,使用 .Equals() 方法来确保正确性,避免使用 == 运算符,因为 == 比较的是引用是否相同,.Equals() 方法才是比较字符串的内容。

  5. 常量字符串

    对于不会改变的字符串,建议定义为常量或只读字段,以提示其他程序员不要修改它们。

  6. 空字符串检查:

    推荐使用 string.IsNullOrEmpty(str)string.IsNullOrWhiteSpace(str) 方法来判断字符串是否为空,这样可以避免一些潜在的错误和陷阱。

总结

好了,今天的分享就到这里啦!

你找到开始那几个问题的答案了吗?

String 是 C# 中一个非常特殊且强大的类型。

掌握它的创建方式、内存管理规则及其特性,能够让你的代码更加高效、优雅。

希望今天的分享对你有帮助!

最后,喜欢文章欢迎点个【赞与在看】,你的支持是我最大的动力!如果你有更好的想法或建议,欢迎留言讨论!

往期精彩

  1. 闲话 .NET(7):.NET Core 能淘汰 .NET FrameWork 吗?
  2. 常用的 4 种 ORM 框架(EF Core,SqlSugar,FreeSql,Dapper)对比总结

我是老杨,一个执着于编程乐趣、至今奋斗在一线的 10年+ 资深研发老鸟,是软件项目管理师,也是快乐的程序猿,持续免费分享全栈实用编程技巧、项目管理经验和职场成长心得,欢迎关注老杨的公众号,和你共同探索代码世界的奥秘!

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2203275.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

插件生成XML

目录 1.数据库配置 2.在pom.xml中添加插件 3.generator文件配置 1.数据库配置 # 数据库配置 spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncodingutf8&useSSLfalseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc…

双主轴车床的优势

双主轴车床作为现代制造业中的一项重要技术,其优势显而易见。下面我将从几个方面详细阐述双主轴车床的优势: ‌一、提高生产效率‌ ‌并行加工‌:双主轴车床最大的特点在于其能够同时在两个主轴上进行加工,这种并行加工方式使得在…

LCD -

LCD 目录 LCD 回顾 应用 - 1、首先将该LCD屏官方写好的三个文件添加进工程中的api文件夹中 - 2、找到LCD的初始化函数 - 3、在LCD屏幕上显示字符串 - 4、在LCD屏幕上显示图片 - 5、在LCD屏幕上显示汉字 例:在LCD屏幕上显示温湿度,时间代码 LC…

Unsupervised Deep Embedding for Clustering Analysis

0. 论文信息 标题:Unsupervised Deep Embedding for Clustering Analysis期刊:International Conference on Machine Learning作者:Junyuan Xie,Ross Girshick,Ali Farhadi机构:University of Washington&…

每日一题|3162. 优质数对的总数 I、II|因子分解、计数方法

第一题非常简单的暴力解法。 class Solution:def numberOfPairs(self, nums1: List[int], nums2: List[int], k: int) -> int:nums2_ [i * k for i in nums2]count 0for i in nums1:for j in nums2_:count 0 if i % j else 1return count 第二题的难度提升在数量级在10万…

[java毕业设计]免费分享一套SpringBoot+Vue电影推荐(电影网)系统【论文+源码+SQL脚本】,帅呆了~~

大家好,我是java1234_小锋老师,看到一个不错的SpringBootVue电影推荐(电影网)系统,分享下哈。 项目视频演示 【免费】SpringBootVue电影推荐(电影网)系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 如今社会上各行各业,都喜欢用…

大数据新视界 --大数据大厂之大数据如何重塑金融风险管理:精准预测与防控

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

第十七篇——无穷小(三):用动态和极限的眼光看世界

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么? 四、总结五、升华 一、背景介绍 这个世界从互联网盛行信息爆炸的时候,就已经进入了无限思维时…

前端环境搭建一览记录

文章目录 写在前面Nodejs下载Nodejs介绍Nodejs下载方式nvm安装:安装Homebrew(安装器)(打开终端,输入下面的脚本)安装nvm验证安装是否成功配置环境内容查看环境内容刷新配置 nvm 使用如何使用nvm ls 查看当前安装的版本nvm use versionId 切换…

鸿蒙开发之ArkUI 界面篇 二十八 ForEach

ForEach语法格式如下: ForEach(数组名字,(Item,index) >{item要做的事情}) 实现下图效果: 代码如下: Entry Component struct IndexTest {State titles:string[] [学鸿蒙,赢取白富美,走向人生巅峰,影音娱乐,海外旅游]build…

并发编程-ReentrentLock概念及使用

1.ReentrantLock概念 ReentrantLock 是 Java 中的一种可重入锁,属于 java.util.concurrent.locks 包。它提供了比 synchronized 关键字更灵活的锁机制,允许更复杂的线程同步控制。以下是 ReentrantLock 的一些关键概念和特点: 可重入性&…

Linux的Redis安装部署

Redis是一个nosql数据库,速度快,key-value型数据库 1.root用户执行 yum install -y epel-release 配置epel仓库 2.安装Redis 命令: yum install -y redis 3.启动服务: systemctl start redis 4.注意关闭firewalld防火墙, 5.进入Redis服务端redis-cli

tensorflow入门案例手写数字识别人工智能界的helloworld项目落地1

参考 https://tensorflow.google.cn/?hlzh-cn https://tensorflow.google.cn/tutorials/keras/classification?hlzh-cn 项目资源 https://download.csdn.net/download/AnalogElectronic/89872174 文章目录 一、案例学习1、导入测试和训练数据集,定义模型&#xff…

el-tree 修改每个层级的背景色

目录 一、思路 二、代码 1. HTML部分 2. js部分 3. css部分 案例图 一、思路 使用 render-content 插槽来自定义节点内容。根据节点的层级动态添加 CSS 类。写一个方法,用于:递归地获取节点的层级。如果节点没有父节点,则返回当前层级…

嵌入式工业显示器在食品生产行业的应用

嵌入式工业显示器在食品生产行业的应用主要体现在以下几个方面: 一、自动化控制与精准监测 嵌入式工业显示器通常与各类传感器和执行器集成,能够实时显示生产线的运行状态,实现自动化控制和精准监测。在食品生产过程中,从原材料…

Vscode+Pycharm+Vue.js+WEUI+django火锅(三)理解Vue

新创建的Vue项目里面很多文件,对于新手,老老实实做一下了解。 1.框架逻辑 框架的逻辑都是相通的,花点时间理一下就清晰了。 2.文件目录及文件 创建好的vue项目下,主要的文件和文件夹要先认识一下,并与框架逻辑对应起…

Centos7 搭建单机elasticsearch

以下是在 CentOS 7 上安装 Elasticsearch 7.17.7 的完整步骤:(数据默认保存在/var/lib/elasticsearch下,自行更改) 一、装 Java 环境 Elasticsearch 是用 Java 编写的,所以需要先安装 Java 运行环境。 检查系统中是…

springboot酒店客房管理系统-计算机毕业设计源码43070

目录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1系统开发流程 2.2.2 用户登录流程 2.2.3 系统操作流程 2.2.4 添加信息流程 2.2.5 修改信息流程 2.2.6 删除信息流程 2.3 系统功能…

模拟堆算法

题目 代码 #include <bits/stdc.h> using namespace std; const int N 1e510; int heap[N], sz, cnt; int th[N], ht[N]; void hswap(int a, int b) {swap(heap[a], heap[b]);swap(ht[a], ht[b]);swap(th[ht[a]], th[ht[b]]); } void down(int h) {int t h;if(2*h <…

【开源项目】Jsoncpp的简单使用

Jsoncpp是一个开源项目&#xff0c;它是一个用于处理JSON&#xff08;JavaScript Object Notation&#xff09;数据的C库。它支持将C结构化的数据转化为JSON字符串&#xff0c;也支持将JSON字符串转化为结构化数据 JSON&#xff08;JavaScript Object Notation&#xff09;数据…