C#中关于字符串的一些特殊点

在C#中,字符串是一个使用比较多的类型,本文会讲到字符串(string)的一些特殊点。

定义

我们先来定义一个字符串类型变量。

string str = "这是一个字符串";

在上面的代码中,我们试用了 stirng 关键字作为类型来定义字符串变量,其实字符串真正的类型为 Stringstring 是作为C#关键字的一个别名,在编码的时候,IDE会给提示,要求我们将 String 修改成 string

我们可以通过反编译来查看 String 的具体定义, String 其实是一个引用类型,派生于 Object 。但是我们在使用的过程中, String 又会表现出值类型的特性(多个变量即使指向了同一个值,在对其中一个变量修改时也不会污染到其他的变量)

public sealed class String : IComparable, ICloneable, IConvertible, IEnumerable, IComparable<string>, IEnumerable<char>, IEquatable<string>
{
}

可以看到 String 类型的定义使用 sealed 关键字,表明 String 类型不可被当作基类继承。 这是因为CLRString 类型做了一些特殊优化,必须防止自定义类型破坏了 CLR 的优化。

这里涉及到 String 类型的一个特性——不变性,即 String 对象一旦创建,就不能再更改.。不变性带来了另一个特性——一致性,即相同的字符串在 CLR 中在表现上同一个对象(其实不是)。这样在使用上, String 类型就和其他的值类型表现一致。不过由于这些特性的存在,所在如果对字符串进行多次修改操作会产生很多临时字符串对象,对性能有影响,所以在很多的库和最佳实践中,都会推荐使用 StringBuilder 来操作。

string str1 = "这是一个字符串";
string str2 = "这是一个字符串";

Console.WriteLine(object.Equals(str1,str2));
// True
Console.WriteLine(object.ReferenceEquals(str1,str2));
// False

可以看到在对象的层面上,两个字符串对象是一致的,这是因为 Equals 比较是靠 GethashCode 方法,而由于 CLR 的特殊优化, String 类型的 GetHashCode 方法会对同样的字符返回一样的哈希值。但是如果我们使用 ReferenceEquals 来比较两个对象的引用还是可以看到其实是两个对象,那么有没有办法做到字符串对象的复用呢?

答案是肯定的,我们只需要使用 Intern 方法即可。

CLR 初始化的时候,会构建一个内部表(暂存池)用来存放 String 对象的引用,而 Intern 方法就是用来访问内部表的,使用 Intern 方法的时候,会先检查内部表中有没有同样的字符串存在,如果有就会直接返回该字符串的引用。所以使用 Intern 方法获得的 String 对象在引用上也是相同的。

string str1 = "这是一个字符串";
string str2 = string.Intern("这是一个字符串");

Console.WriteLine(object.Equals(str1,str2));
// True
Console.WriteLine(object.ReferenceEquals(str1,str2));
// True

当然上面的测试都是在 .net 6的环境中进行的,如果 CLR 的实现不同,对于字符串的优化也有可能不同,甚至在 CLR 中默认开启字符串池,直接把相同值得字符串对象彻底优化成一个引用也是可能的。

发布时间:2024-08-09

其他阅读

静态文件防盗链的一种思路

在我们的系统中,总会有一些资源需要保护起来不被盗走,如果是动态接口可以通过验证权限来保护,静态资源大多需要对外开放,比较难以保护,本文就介绍保护静态文件资源一种思路——那就是使用 HTTP 中 Referer 头。

git的一些技巧

git 是一个免费开源分布式版本控制系统,可以高效处理从小型到超大型项目内容管理,本文会介绍一些 git 使用的技巧。

使用中间件记录网站访问日志记录

对于网站访问日志的记录,一般情况下都是使用现有的日志服务,比如谷歌分析引入轻量 js 文件即可。本文主要介绍对于现有的 Asp.Net Core 网站使用中间件快速记录访问日志。使用中间件的好处:在服务端进行处理,无视客户端类型(特殊信息无法获取);统一处理,不需要对每个地址重复处理等。

Nginx重定向HTTP到HTTPS

HTTP协议以纯文本形式进行数据的交互,数据明文传输,容易被监听,窃取和伪造,HTTPS在HTTP的基础上,使用了TLS/SSL对通信过程进行加密,数据得到了有效的保护,就算被拦截到也无法获取信息,更没法实施中间人攻击。本文将会介绍如何在Nginx中配置HTTP重定向到HTTPS。

Web前端中实现一个拖动效果

在原生客户端开发中,窗口拖动是一个比较常用的操作。今天把这个效果在网页客户端中实现以下,文章记录一下效果。