.NET中的空数组是否使用任何空间?

Ori*_*rds 24 .net c# arrays

我有一些代码,我正在返回一个对象数组.

这是一个简化的例子:

string[] GetTheStuff() {
    List<string> s = null;
    if( somePredicate() ) {
        s = new List<string>(); // imagine we load some data or something
    }
    return (s == null) ? 
        new string[0] :
        s.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

问题是,这有多贵new string[0]
我应该只返回null并使调用者接受null作为指示"未找到任何内容"的有效方式吗?

注意:这是在一个循环中调用的,它会运行数百次,所以这是我认为这种优化实际上并不"过早"的少数情况之一.

PS:即使它还为时过早,我仍然想知道它是如何工作的:-)

更新:

最初当我问它是否使用了任何空间时,我从'C/C++'的角度思考问题,有点像在C中,写入char a[5];将在堆栈上分配5个字节的空间,char b[0];并将分配0个字节.

我意识到这不适合.NET世界,但我很好奇,如果这是编译器或CLR将检测和优化的东西,因为一个大小为零的不可调整大小的数组真的不应该(至于我可以看到?)需要任何存储空间.

Jon*_*eet 56

即使它被称为"数百和数百"次,我也会说这是一个不成熟的优化.如果结果作为空数组更清晰,请使用它.

现在得到实际答案:是的,一个空数组需要一些内存.它具有正常的对象开销(我相信x86上为8个字节),计数为4个字节.我不知道除此之外还有什么,但它并不是完全免费的.(它虽然便宜......)

幸运的是,您可以在不牺牲API本身的情况下进行优化:拥有空数组的"常量".如果你允许的话,我已经做了另一个小改动,使代码更清晰......

private static readonly string[] EmptyStringArray = new string[0];

string[] GetTheStuff() {
    if( somePredicate() ) {
        List<string> s = new List<string>(); 
        // imagine we load some data or something
        return s.ToArray();
    } else {
        return EmptyStringArray;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你经常发现自己需要这个,你甚至可以创建一个带有静态成员的泛型类来返回一个正确类型的空数组..NET泛型的工作方式使这一点变得微不足道:

public static class Arrays<T> {
    public static readonly Empty = new T[0];
}
Run Code Online (Sandbox Code Playgroud)

(当然,你可以将它包装在一个属性中.)

然后只需使用:Arrays <string> .Empty;

编辑:我刚刚记得Eric Lippert关于数组的帖子.您确定数组是最合适的类型吗?

  • ffpf:如何在空数组中粘贴某些东西?是的,只有数组引用是只读的 - 但数组仍然是固定大小,0. (8认同)
  • 另请参阅我对新的`Array.Empty <string>()`方法的回答,我想这将使您无需编写`Arrays <string> .Empty`属性. (2认同)

Jep*_*sen 9

即将推出的.NET 4.6版(2015年晚些时候)包含一个返回长度为零的静态方法string[]:

Array.Empty<string>()
Run Code Online (Sandbox Code Playgroud)

我想如果多次调用它会返回相同的实例.


Jon*_*jap 5

声明的数组总是必须包含以下信息:

  • 等级(维数)
  • 要包含的类型
  • 每个维度的长度

这很可能是微不足道的,但是对于更大数量的尺寸和更长的长度,它将对环路产生性能影响.

至于返回类型,我同意应该返回一个空数组而不是null.

更多信息:.NET中的数组类型