是否可以创建一个不是引用的字符串 - 等于任何其他字符串?

mil*_*ose 6 .net c# string referenceequals

似乎.NET不愿意通过引用使值相等的字符串.

在LINQPad中,我尝试了以下内容,希望它绕过内部字符串常量:

var s1 = new string("".ToCharArray());
var s2 = new string("".ToCharArray());

object.ReferenceEquals(s1, s2).Dump();
Run Code Online (Sandbox Code Playgroud)

但那又回来了true.但是,我想创建一个string可以与任何其他string对象可靠区分的东西.

(用例是创建一个用于可选参数的标记值.我正在包装WebForms' Page.Validate(),我想根据调用者是否给我提供可选的验证组参数来选择适当的重载.所以我希望能够检测调用者是否省略了该参数,或者他是否传递了一个恰好等于我的默认值的值.显然,还有其他不那么神秘的方法来处理这个特定的用例,这个问题的目的更具有学术性.),

Dan*_*Tao 6

似乎.NET不愿意通过引用使值相等的字符串.

实际上,对于字符串来说,实际上只有两种特殊情况表现出类似于您在此处描述的行为:

  1. 代码中的字符串文字是实体的,因此两个地方的相同文字将导致对同一对象的引用.
  2. 所述空字符串是一个特别怪异情况下,当如据我所知字面上在.NET程序中的每个空串实际上是在同一个对象(即,"每一空字符串"构成单个字符串).这是我在.NET中所知道的唯一一种情况,使用new关键字(在类上)可能不会导致新对象的分配.

根据您的问题,我得到您已经了解的第一个案例的印象.第二种情况是你偶然发现的那种情况.正如其他人指出的那样,如果你只是继续使用非空字符串,你会发现创建一个非引用的字符串很容易 - 等于程序中的任何其他字符串:

public static string Sentinel = new string(new char[] { 'x' });
Run Code Online (Sandbox Code Playgroud)

除了一点点编辑之外,我实际上并不介意这么多(只要记录在案); 但有点让我感到不安的是,CLR人员(?)实现了这种优化,而没有继续前进并为数组做同样的事情.也就是说,在我看来,他们也可能继续前进,并且每个人也都new T[0]指向同一个对象.或者,你知道,也没有为字符串做过.