我注意到了
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不这样做?有什么我想念的吗?
字符串可以使用实习,这使得它们成为不同的故事(来自所有其他类型的对象).
数组本质上只是对象.重复使用语法或上下文中不明确的实例并非没有副作用或风险.
static int[] empty = new int[0];
...
lock (empty) { ... }
Run Code Online (Sandbox Code Playgroud)
如果某些其他代码锁定在另一个(他们认为)为空,int[]那么您可能会遇到很难找到的死锁.
其他场景包括使用数组作为词典中的键,或者其他任何地方的身份都很重要.框架不能只是改变规则.