C#拾遗补阙【01】:字符串
一、string是特殊的引用类型
众所周知,string是引用类型。为什么string是引用类型,最简单的方法,f12转到string的定义。显而易见,string的本质是类,字符串存储在堆中,而string作为关键字,是String的别名。
然而,实例一个string对象不需要使用 new 关键字,而是直接使用字面值字符串,如:
string str= "Hello";
Console.WriteLine(str);
Console.ReadKey();
用ILSpy查看上述的代码IL,未出现预期的IL指令newobj,只有一个特殊的ldstr指令,CLR使用一种特殊的方式构造string对象。
当然,String类也提供了不同的构造函数,可使用new构造字符串,如:
试着用new构造一个string对象,查看其产生的IL,惊喜的发现new构造的字符串使用IL指令newobj。
string str= new string(new char[] { 'H', 'e', 'l', 'l', 'o' });
二、string是不可变的
string对象最为重要的一个特征:字符串一旦创建便是恒定不变,字符串一经创建便不能更改,不能边长、变短或修改字符。string对象发生修改时,实际上不会改变原来的值,而是在托管堆中重新创建一个新的字符串,将新的引用地址传递给string对象,如下图代码和托管堆变化示例
string str= "Hello";
str = "你好";
由上图可知,每次对字符串进行操作,都需要在托管堆中重新分配一个新的空间地址来存储字符串,如果频繁操作某一个string对象字符串,会在堆上创建大量的对象,从而影响性能。如果需要频繁操作字符串,推荐使用StringBuilder。下面是string和StringBuilder简单的对比:
string str= string.Empty;
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 10000; i++)
{
str += "Hello World";
}
watch.Stop();
Console.WriteLine(watch.Elapsed);
watch.Restart();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
sb.Append("Hello World");
}
watch.Stop();
Console.WriteLine(watch.Elapsed);
三、字符串驻留
字符串是我们十分频繁使用的类型,由于字符串是不可变的特性,会创造大量的对象,因而有了字符串驻留。先看看下面的例子:
string str1 = "Hello";
string str2 = "Hello";
Console.WriteLine(object.ReferenceEquals(str1,str2));
输出:True。也就是说,str1和str2这两个string对象都引用了同一个内存地址
接下来继续拓展示例:
string str1 = "Hello";
string str2 = "Hello";
string str3 = " LiMing";
string str4 = "Hello LiMing";
string str5 = "Hello" + " LiMing";
string str6 = str3 + " LiMing"; ;
string str7 = str3 + str4;
Console.WriteLine(object.ReferenceEquals(str1,str2));
Console.WriteLine(object.ReferenceEquals(str4, str5));
Console.WriteLine(object.ReferenceEquals(str4, str6));
Console.WriteLine(object.ReferenceEquals(str4, str7));
从上面的例子不难发现,并不是所有相等的字符串的地址都是一样的。实际上,在CLR内部维护了一个哈希表,在这个哈希表中,key时字符串,value是托管堆中的地址。在程序运行中,CLR将字面值(形如str1)的字符串,都会通过驻留机制,将这些字符串进行维护到哈希表中。当s创建str1时,会先判断是否在哈希表中有相同的字符串,如果没有,则创建一个新的对象;当创建str2时,哈希表中已经有相同的字符串时,直接返回已有的引用地址给str2。那为什么str6、str7的引用地址和str4不相同呢?因为str6、str7是动态字符串,即非字面值的字符串。
《CLR Via C#》
C#拾遗补阙【01】:字符串的更多相关文章
- hiho #1326 : 有序01字符串
#1326 : 有序01字符串 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于一个01字符串,你每次可以将一个0修改成1,或者将一个1修改成0.那么,你最少需要修改 ...
- 深度优先搜索 codevs 1065 01字符串
codevs 1065 01字符串 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 输出仅有0和1组成的长度为n的字符串,并且 ...
- Codevs 1065 01字符串
1065 01字符串 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 传送门 题目描述 Description 输出仅有0和1组成的长度为n的字符串,并且其中不能含有 ...
- hiho 有序01字符串 dp
题目1 : 有序01字符串 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于一个01字符串,你每次可以将一个0修改成1,或者将一个1修改成0.那么,你最少需要修改多少 ...
- codevs——1065 01字符串
1065 01字符串 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 输出仅有0和1组成的长度为n的字符串, ...
- NPU 2015年陕西省程序设计竞赛网络预赛(正式赛)F题 和谐的比赛(递推 ||卡特兰数(转化成01字符串))
Description 今天西工大举办了一场比赛总共有m+n人,但是有m人比较懒没带电脑,另外的n个人带了电脑.不幸的是,今天机房的电脑全坏了只能用带的电脑,一台电脑最多两人公用,确保n>=m. ...
- P1071 01字符串的交叉安排
题目描述 你有 \(n(1 \le n \le 10^6)\) 个字符'0' 和 \(m(1 \le m \le 10^6)\) 个字符'1'.你需要使用这些字符拼接成一个01字符串,使得满足如下两个 ...
- SYCOJ#1077、01字符串
题目-01字符串 (shiyancang.cn) 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 ...
- JS 实现"可读"字符串转换成"二进制的01"字符串
问题起源 看过一个漫画, 两位程序员在办公司交流, 可是说的语言却是010101类似的字符串.周围人很是惊异.计算机的世界,确实是由01组成的.今天突然想实现这个编码转换. 解决思路 学过C语言的都知 ...
- 【codevs1065】01字符串
题目大意:输出仅由 0 和 1 组成的长度为 N 的字符串个数,并且其中不能含有 3 个连续的相同子串. 题解:数据太水,正规解法应该是枚举后缀进行判断. 代码如下 #include <bits ...
随机推荐
- 看我如何使用 shell 来获取所有 KVM 虚拟机的 IP 地址
文章目录 脚本说明 脚本展示 效果展示 此脚本的初衷是因为,KVM创建的桥接网卡的虚拟机,无法使用virsh domifaddr命令获取IP,而创建的nat网卡的虚拟机,则可以直接使用virsh do ...
- OpenStack、虚拟机以及和当前流行的k8s、Docker四者之间的关系
一.OpenStack与虚拟机之间的关系 OpenStack使用Python语言开发,是虚拟资源管理工具,他可以协助你搜集各种资源,并加以利用以及管理,实现物理资源的高效使用和安全.虚拟化物理机这个动 ...
- 关于 share 音乐分享官方文档补充
例子 音乐分享 /*--------微信朋友圈--------*/ [shareParams SSDKSetupWeChatParamsByText:@"内容" title:@&q ...
- RadonDB MySQL on K8s 2.1.2 发布!
RadonDB MySQL on Kubernetes 于 2 月 17 日发布了新版本 2.1.2 .该版本在节点的重建.增删等方面进行了全面升级. 致谢: 首先感谢 @andyli029 @ace ...
- Bypass BeaconEye - Beacon 堆混淆
这是[信安成长计划]的第 9 篇文章 关注微信公众号[信安成长计划] 0x00 目录 0x01 CS4.5 Sleep_Mask 0x02 HeapEncrypt 0x03 效果 0x04 参考文章 ...
- 浅谈:redis的主从复制 + 哨兵模式
浅谈:redis的主从复制 + 哨兵模式 主从模式 在谈论redis的主从复制之前,我们先回想下mysql的主从搭建过程,第一步呢首先要在主库服务器中修改my.cnf,开启一下bin_log功能, ...
- 为什么越来越多的企业选择商业智能BI?
在大数据,云计算,工业4.0,物联网等概念概念炒得飞起的年代,现在已经变成某宝天天给我推送我感兴趣的东西.由此可见数据和科技正在慢慢深刻地改变我们的生活. 随着时代的发展,各个企业的内部决策方式也是 ...
- Hook(钩子技术)基本知识讲解,原理
一.什么是HOOK(钩子) API Windows消息传递机制,当在应用程序进行相关操作,例如点击鼠标.按下键盘,操作窗口等,操作系统能够感知这一事件,接着把此消息放到系统消息队列,然后到应用程序的 ...
- 彻底关闭 win10家庭版 杀毒软件windows defender
下面开始今天的教程, 第一步,我们先在windows安全中心将相关的设置关闭一下,具体方法如下: 我们右键点击windows 10开始菜单,点击"设置", 点击"设置&q ...
- 2020.9.28 多进程multiprocess 进程池pool 子进程subprocess 进程间通信
1.multiprocessing模块--跨平台版本的多进程模块 multiprocessing模块提供了一个Process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束: from ...