如何在C#中初始化一个空数组?


Answers:


434

如果要使用事先不知道其大小的集合,则有比数组更好的选择。

使用List<string>代替-这将允许您添加尽可能多的项目,你需要,如果你需要返回一个数组,调用ToArray()该变量。

var listOfStrings = new List<string>();

// do stuff...

string[] arrayOfStrings = listOfStrings.ToArray();

如果必须创建一个空数组,可以执行以下操作:

string[] emptyStringArray = new string[0]; 

1
@Oded-string [] emptyStringArray =新字符串[0]; 不会导致一个空数组,对吗?看起来这是一个具有一个元素的数组,其中该元素为null。
rory.ap 2013年

11
@roryap-否。结果是string[]没有元素。如果您尝试访问emptyStringArray[0],则将获得IndexOutOfRangeException
Oded

@Oded-谢谢,我是C#的新手。在VB中,提供的索引是上限,而不是元素数。
rory.ap 2013年

1
您认为更好的是:var strings = new string [] {}; 或var字符串=新字符串[0];顺便说一句:我认为空数组是方法参数的完全有效默认值:public void EditItems(IEnumerable <Item> toEdit,IEnumerable <long> toDelete = new long [] {})
realbart 2014年

6
@ RickO'Shea-C ++不是C#。Stroustrup知道他的C ++-不确定他知道他的C#和.NET GC。不会和你进行宗教战争。
Oded

181

尝试这个:

string[] a = new string[] { };

7
扩展这个答案,您还可以在不指定大小或类型的情况下使用项初始化数组,编译器将从初始化程序中推断:var a = new [] {“ a”,“ b”,“ c”}; 这仍然是一个强类型的字符串数组。
Nick VanderPyle,2012年

1
未处理的异常:System.IndexOutOfRangeException:索引在数组边界之外。在ArrayClass.Main(String [] args)。我更改了int []变量= new int [] {}后遇到了这个错误
yogesh 2012年

6
@yogesh:真奇怪。例如int[] variable = new int[]{},当在诸如foreach (var s in variable){ Console.WriteLine(s);}代码之类的循环中编写和使用它时,代码将编译为:int[] args1 = new int[0];foreach (int num in args1){Console.WriteLine(num);}。因此,使用new int[0]new int[]{}将两者编译为同一代码之间应该没有区别。
2012年

1
@GlennGordon绝对是,但这是C#3.0版(从2007年开始,使用Visual Studio 2008)中的新增功能。该版本还允许使用的另一种简单格式var,尽管仅适用于局部变量(不适用于字段)。但是,在C#2.0(Visual Studio 2005)和更早版本中,您必须使用此答案(或string[] a = new string[0];)的语法。
杰普·斯蒂格·尼尔森

113

在.NET 4.6中,首选方法是使用新方法Array.Empty

String[] a = Array.Empty<string>();

实现简洁,使用泛型类的静态成员如何在.net中的行为

public static T[] Empty<T>()
{
    return EmptyArray<T>.Value;
}

// Useful in number of places that return an empty byte array to avoid
// unnecessary memory allocation.
internal static class EmptyArray<T>
{
    public static readonly T[] Value = new T[0];
}

(为清楚起见,删除了与代码合同相关的代码)

也可以看看:


@Cole Johnson-感谢您的修改,但我将其回滚了。我故意省略了这些行:我只想引用有趣的实现。代码协定和属性只会妨碍您了解正在发生的事情(当然,到源的链接包含了所有内容)。我还在注释中添加了换行符,以避免在Stack Overflow上滚动。如果您不介意,我会喜欢这种方式。谢谢!
科比

2
从以下方面绝对提高了可读性:Enumerable.Empty<T>().ToArray()
DanielV

即使在大多数情况下绝对首选此方法,它也不能回答原始问题。OP希望创建一个空数组。Array.Empty<T>()没有建立一个数组。它返回对预分配数组的引用。
l33t

33

您可以将其初始化为大小为0,但是当您知道大小为0时,由于无法追加到数组,因此必须重新初始化它。

string[] a = new string[0];

这是准确的答案
Abzarak

7

声明没有大小的数组没有多大意义。一个数组大约是size。声明特定大小的数组时,请在集合中指定可容纳事物的固定可用插槽数,并相应地分配内存。要向其中添加一些内容,无论如何您都需要重新初始化现有的数组(即使您要调整数组的大小,也请参见此线程)。您想初始化一个空数组的罕见情况之一是将array作为参数传递。

如果要在不知道集合的大小的情况下定义集合,则数组不是您的选择,而是类似a List<T>或类似的东西。

就是说,声明数组而不指定大小的唯一方法是拥有一个大小为0的空数组。hemantAlex Dn提供了两种方法。另一个更简单的选择是

string[] a = { };

[ 括号内的元素应隐式转换为定义的类型,string[] a = { "a", "b" }; ]

还是另一个:

var a = Enumerable.Empty<string>().ToArray();

这是一种更具声明性的方式

public static class Array<T>
{
    public static T[] Empty()
    {
        return Empty(0);
    }

    public static T[] Empty(int size)
    {
        return new T[size];
    }
}

现在您可以致电:

var a = Array<string>.Empty();

//or

var a = Array<string>.Empty(5);

1
除了将数组作为参数传递外,我想不出任何用处。在几种情况下,一种方法接受一个对象数组,而您可能希望传递一个空数组以实现默认操作。我将编辑我的答案。
nawfal 2015年

例如,您有一个由多个类实现的接口,这些类返回一个IEnumerable,并且其中一个实现不包含该方法的元素,例如,返回一个空数组。
Ignacio Soler Garcia 2015年

@IgnacioSolerGarcia在这种情况下,当且仅当它是对性能至关重要的应用程序时,我才会返回一个数组。我会说数组已经过时了,如果可以的话应该避免使用。看到利珀特(Lippert)提出的问题,
nawfal 2015年

请记住,返回的类型是IEnumerable,因此该数组是只读的,并且不打算更改。例如,为什么在这种情况下我会返回列表?
Ignacio Soler Garcia 2015年

1
空数组的用例很简单-当您想用对象填充它而又不知道要添加多少个对象时!
vapcguy,2015年

6

简洁大方!

string[] array = {}

我将更array改为just aarray大写时作为关键字。将关键字名用作变量名只是一种不好的做法-即使大小写不同也是如此。与我的答案基本相同,除了我String.Empty在那里。
vapcguy19年

1
1.数组不是ac#关键字。数组是一个类,而不是关键字2。“ a”也是一种不好的做法(甚至比使用关键字还要糟糕)
disklosr

技术性。类,关键字,它定义了一个对象类型并且仍然很糟糕。你为什么认为a不好?
vapcguy19年

1
因为非描述性和一字母变量名称是不好的做法,因为它们没有传达定义它们的原因。“数组”当然比“ a”更好。更好的名称是“ emptyArray”。
disklosr

4

string[] a = new string[0];

或简称:

string[] a = { };

现在首选的方法是:

var a = Array.Empty<string>();

我写了一个简短的正则表达式,如果要替换零长度分配,可以在Visual Studio中使用new string[0]。在启用正则表达式的情况下在Visual Studio中使用“查找(搜索)”选项:

new[ ][a-zA-Z0-9]+\[0\]

现在,查找全部或F3(查找下一个),并将其全部替换为Array.Empty <…>()!


3

您可以在运行时定义数组大小

这将允许您执行任何操作来动态计算阵列的大小。但是,一旦定义大小是不可变的。

Array a = Array.CreateInstance(typeof(string), 5);

4
为什么要那样做?在运行时,您可以正常地从变量定义数组大小:int i = 5; string[] a = new string[i];
Kevin Brock 2012年

好吧,我想使用泛型似乎已经过时了。
radarbob

2

我试过了:

string[] sample = new string[0];

但是我只能在其中插入一个字符串,然后出现exceptionOutOfBound错误,因此我只需要为其加上一个大小即可,例如

string[] sample = new string[100];

或对我有用的另一种方式:

List<string> sample = new List<string>();

为列表分配值:

sample.Add(your input);

1

据我所知,没有大小就无法制作数组,但是可以使用

List<string> l = new List<string>() 

然后l.ToArray()


1

结合@nawfal和@Kobi建议:

namespace Extensions
{
    /// <summary> Useful in number of places that return an empty byte array to avoid unnecessary memory allocation. </summary>
    public static class Array<T>
    {
        public static readonly T[] Empty = new T[0];
    }
}

用法示例:

Array<string>.Empty

更新2019-05-14

(归功于@Jaider ty)

更好地使用.Net API:

public static T[] Empty<T> ();

https://docs.microsoft.com/zh-cn/dotnet/api/system.array.empty?view=netframework-4.8

适用于:

.NET Core:3.0预览版5 2.2 2.1 2.0 1.1 1.0

.NET Framework:4.8 4.7.2 4.7.1 4.7 4.6.2 4.6.1 4.6

.NET标准:2.1预览版2.0 1.6 1.5 1.4 1.3

...

高温超导


1
在.NET Core 2中,已经对其进行了扩展arr = Array.Empty<string>();
Jaider

iirc,在.NetStandart [4.something]中-也有。
ShloEmi

0

你可以做:

string[] a = { String.Empty };

注:OP意味着不必指定大小,而不是让一个数组没有尺寸


7
这不会创建长度为1的字符串数组吗?
Sumner Evans

是的,但已清除。OP要求声明数组而不必声明大小-这很合适。
vapcguy,2015年

那值得一票,为什么呢?OP的意思是不必设置specify大小,也可以不创建数组sizeless
vapcguy 2015年

1
@vapcguy我是低俗主义者。我后悔了。我已经编辑了您的答案以取消我的否决票。您的评论使这个问题有些疑问。不知道这是OP的意思。
nawfal

4
OP要求输入一个数组。该数组不为空。
基思

0

这是一个真实的例子。在这种情况下,必须foundFiles首先将数组初始化为零长度。

(如在其他答案中所强调的:这不会初始化元素,尤其是不会初始化索引为零的元素,因为这将意味着数组的长度为1。此行之后的数组长度为零!)。

如果= string[0]省略该部分,则存在编译器错误!

这是因为捕获块没有被重新抛出。C#编译器识别代码路径,该函数Directory.GetFiles()可以引发Exception,以便可以对数组进行未初始化。

在任何人说之前,不抛出异常将是错误的错误处理:这不是事实。错误处理必须符合要求。

在这种情况下,假定程序在目录无法读取且不中断的情况下应继续执行-最佳示例是遍历目录结构的函数。这里的错误处理只是记录它。当然,这样做可以做得更好,例如,将所有包含失败GetFiles(Dir)调用的目录收集在列表中,但这在这里可能会导致过多的后果。

足以说明避免throw是有效的情况,因此必须将数组初始化为长度为零。在catch块中执行此操作就足够了,但这将是不好的样式。

调用以GetFiles(Dir)调整数组大小。

string[] foundFiles= new string[0];
string dir = @"c:\";
try
{
    foundFiles = Directory.GetFiles(dir);  // Remark; Array is resized from length zero
}
// Please add appropriate Exception handling yourself
catch (IOException)
{
  Console.WriteLine("Log: Warning! IOException while reading directory: " + dir);
  // throw; // This would throw Exception to caller and avoid compiler error
}

foreach (string filename in foundFiles)
    Console.WriteLine("Filename: " + filename);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.