为什么CLR重用空字符串,而不是空数组?

Tim*_*mwi 14 .net clr

我注意到了

Console.WriteLine((object) new string(' ', 0) == (object) new string(' ', 0));
Run Code Online (Sandbox Code Playgroud)

print true,表示CLR保留空字符串并重新使用同一实例.(它打印false的除了以外的任何其他数字0.)

但是,对于数组而言,情况并非如此:

Console.WriteLine(new int[0] == new int[0]);   // False
Run Code Online (Sandbox Code Playgroud)

现在,如果我们查看实现Enumerable.Empty<T>(),我们发现它缓存并重新使用空数组:

public static IEnumerable<TResult> Empty<TResult>()
{
    return EmptyEnumerable<TResult>.Instance;
}

[...]

public static IEnumerable<TElement> Instance
{
    get
    {
        if (EmptyEnumerable<TElement>.instance == null)
            EmptyEnumerable<TElement>.instance = new TElement[0];
        return EmptyEnumerable<TElement>.instance;
    }
}
Run Code Online (Sandbox Code Playgroud)

所以框架团队觉得为每种类型保持一个空阵列是值得的.如果想要,CLR可以更进一步,并且本地执行此操作,因此它不仅适用于呼叫,Enumerable.Empty<T>()还适用于new T[0].如果优化Enumerable.Empty<T>()是值得的,那肯定会更值得吗?

为什么CLR不这样做?有什么我想念的吗?

Hen*_*man 9

字符串可以使用实习,这使得它们成为不同的故事(来自所有其他类型的对象).

数组本质上只是对象.重复使用语法或上下文中不明确的实例并非没有副作用或风险.

static int[] empty = new int[0];
...
   lock (empty) { ... }
Run Code Online (Sandbox Code Playgroud)

如果某些其他代码锁定在另一个(他们认为)为空,int[]那么您可能会遇到很难找到的死锁.

其他场景包括使用数组作为词典中的键,或者其他任何地方的身份都很重要.框架不能只是改变规则.

  • 今天我了解到那里的人把绳子锁上了. (5认同)
  • 只有string*literals*默认使用interning - 而字符串基本上只是对象.改变你的例子使用`static string empty = new string('',0)` - 它看起来有效吗? (2认同)
  • Henk的观点仍然表明,如果CLR团队完全考虑这个功能,那将是一个考虑点. (2认同)