所有可能的数组初始化语法

886

有哪些C#数组初始化语法可用?

20个回答

963
这是一个简单数组的当前声明和初始化方法。
string[] array = new string[2]; // creates array of length 2, default values
string[] array = new string[] { "A", "B" }; // creates populated array of length 2
string[] array = { "A" , "B" }; // creates populated array of length 2
string[] array = new[] { "A", "B" }; // creates populated array of length 2
string[] array = ["A", "B"]; // creates populated array of length 2

请注意,还有其他获取数组的技术,例如在`IEnumerable`上使用Linq的`ToArray()`扩展方法。
还要注意,在上面的声明中,前两个声明可以用`var`(C# 3+)替换左侧的`string[]`,因为右侧的信息足以推断出正确的类型。第三行必须按照显示的方式编写,因为仅使用数组初始化语法无法满足编译器的要求。第四行也可以使用推断。第五行是在C# 12中引入的集合表达式,其中目标类型无法推断。它也可以用于跨度和列表。如果你喜欢简洁的写法,上述内容可以写成这样:
var array = new string[2]; // creates array of length 2, default values
var array = new string[] { "A", "B" }; // creates populated array of length 2
string[] array = { "A" , "B" }; // creates populated array of length 2
var array = new[] { "A", "B" }; // created populated array of length 2
string[] array = ["A", "B"]; // creates populated array of length 2

7
出于好奇,有人能解释一下为什么第三行的初始化表达式不能单独使用(例如传递到方法中)或分配给var变量吗? - Ruben9922
2
@Ruben9922:有趣的问题。如果数组初始化器可以产生除数组之外的任何其他内容,那么var x = {}就毫无意义了,但我不知道什么是这种情况。所以,我猜测数组初始化器是一种语言特性。如果你将它与new List<string> {"A", "B"}一起使用,它也会产生不同的结果。 - TvdH
1
有没有任何理由使用 string array = new string[] { "A", "B" }; 而不是 string array = { "A", "B" };?第一个似乎多余了。 - Lou
1
@Lou 语法来自于在无法自动推断类型的情况下明确指定类型的能力。但当然,在原始字符串类型的情况下,这种表示法肯定是多余的。 - Lorenzo
2
@Ruben9922:有趣的是,在VB.NET中,Dim a = { "A", "B" } 确实可以工作(使用Option Strict On和Option Infer On),并且正确地推断出String()(在C#中为string[])作为数据类型,所以我猜C#设计者故意选择不支持这个。我想在VB中更容易实现,因为VB仅在数组初始化时使用花括号(与C#不同,在C#中你到处都可以看到花括号)。在VB中,您还可以编写Return {}来返回一个数组的方法。 - Heinzi
C#12的集合表达式也可以用于Lists<>等,它们还可以很好地实例化一个空的Array/List,就像这样:string[] arr = []List<string> list = [] 附加链接 - undefined

474

C# 中用作 表达式 的数组创建语法包括:

new int[3]
new int[3] { 10, 20, 30 }
new int[] { 10, 20, 30 }
new[] { 10, 20, 30 }
在第一种情况下,大小可以是任何非负整数值,并且数组元素将初始化为默认值。
在第二种情况下,大小必须是一个常数,并且给出的元素数量必须匹配。必须存在从给定元素到给定数组元素类型的隐式转换。
在第三种情况下,元素必须能够隐式转换为该元素类型,并且大小由给定的元素数量确定。
在第四种情况下,通过计算具有类型的所有给定元素的最佳类型(如果有)来推断数组元素的类型。所有元素都必须能够隐式转换为该类型。大小由给定的元素数量确定。此语法是在C# 3.0中引入的。
还有一种语法只能在声明中使用:
int[] x = { 10, 20, 30 };

元素必须隐式转换为元素类型。大小是根据给定元素数确定的。

没有一个全能指南

我向您推荐C# 4.0规范,第7.6.10.4节"数组创建表达式"。


8
你提到的第一个语法是“隐式类型数组创建表达式”,第二个是“匿名对象创建表达式”。你没有列出另外两种类似的语法,它们是“对象初始化程序”和“集合初始化程序”。 - Eric Lippert
14
虽然不完全是C#的“语法”,但别忘了(我个人最喜欢的)Array.CreateInstance(typeof(int), 3) - Jeffrey L Whitledge
18
@Jeffrey:如果我们要走这条路,那就开始变得愚蠢了。例如,"1,2,3,4".split(',') - Brian
16
对于多维数组,存在着“嵌套”表示方法,如 new int[,] { { 3, 7 }, { 103, 107 }, { 10003, 10007 }, };int[,,]int[,,,] 等也可以采用类似的��式。 - Jeppe Stig Nielsen
8
@Learning-Overthinker-Confused: 你有两匹马,希望知道哪一匹更快。你会选择(1)让这两匹马比赛,还是(2)询问一个从未见过这两匹马的陌生人,他认为哪一匹更快? 请比赛你的马。如果你想知道哪一匹更“高效”?首先要创建可衡量的效率标准;请记住,效率是单位成本所产生的价值,因此请仔细定义你的价值和成本。然后编写代码并测量其效率。使用科学来回答科学问题,而不是向随机陌生人询问猜测。 - Eric Lippert
显示剩余8条评论

130

非空数组

  • var data0 = new int[3]

  • var data1 = new int[3] { 1, 2, 3 }

  • var data2 = new int[] { 1, 2, 3 }

  • var data3 = new[] { 1, 2, 3 }

  • var data4 = { 1, 2, 3 } 无法编译。请使用 int[] data5 = { 1, 2, 3 } 替代。

空数组

  • var data6 = new int[0]
  • var data7 = new int[] { }
  • var data8 = new [] { }int[] data9 = new [] { } 无法编译。

  • var data10 = { } 无法编译。请使用 int[] data11 = { } 替代。

作为方法参数

只有可以用 var 关键字赋值的表达式才能作为参数传递。

  • Foo(new int[2])
  • Foo(new int[2] { 1, 2 })
  • Foo(new int[] { 1, 2 })
  • Foo(new[] { 1, 2 })
  • Foo({ 1, 2 }) 无法编译
  • Foo(new int[0])
  • Foo(new int[] { })
  • Foo({}) 无法编译

15
更清晰地区分有效的语法和无效的语法是很好的。 - jpmc26

59
Enumerable.Repeat(String.Empty, count).ToArray()

将创建一个空字符串数组,重复“count”次。 如果您想使用相同但特殊的默认元素值初始化数组,请小心引用类型,所有元素将引用同一对象。


11
是的,在 var arr1 = Enumerable.Repeat(new object(), 10).ToArray(); 中,你会得到对同一对象的 10 个引用。要创建 10 个不同的对象,您可以使用 var arr2 = Enumerable.Repeat(/* dummy: */ false, 10).Select(x => new object()).ToArray(); 或类似方法。 - Jeppe Stig Nielsen

26
var contacts = new[]
{
    new 
    {
        Name = " Eugene Zabokritski",
        PhoneNumbers = new[] { "206-555-0108", "425-555-0001" }
    },
    new 
    {
        Name = " Hanying Feng",
        PhoneNumbers = new[] { "650-555-0199" }
    }
};

你应该如何使用这个结构?它像字典一样吗? - R. Navega
1
@R.Navega 这是一个普通数组 :) - grooveplex
@grooveplex 这是一个匿名类型的数组。这些匿名类型包含了成员Name,类型为string和PhoneNumbers,类型为string[]。这些类型由编译器推断。 - Suncat2000

25

如果您想要初始化一个固定长度的预先初始化的元素相等的数组(非null或其他default值),请使用以下代码:

在此情况下,您可以使用以下代码来初始化一个预先初始化的、具有相等元素的固定长度数组(元素必须是非null或不同于default值):

var array = Enumerable.Repeat(string.Empty, 37).ToArray();

请您也参与此次讨论。


14

创建自定义类数组的示例

下面是该类的定义。

public class DummyUser
{
    public string email { get; set; }
    public string language { get; set; }
}

你可以这样初始化数组:

private DummyUser[] arrDummyUser = new DummyUser[]
{
    new DummyUser{
       email = "abc.xyz@email.com",
       language = "English"
    },
    new DummyUser{
       email = "def@email.com",
       language = "Spanish"
    }
};

11

提示

以下数组:

string[] array = new string[2];
string[] array2 = new string[] { "A", "B" };
string[] array3 = { "A" , "B" };
string[] array4 = new[] { "A", "B" };

将被编译为:

string[] array = new string[2];
string[] array2 = new string[] { "A", "B" };
string[] array3 = new string[] { "A", "B" };
string[] array4 = new string[] { "A", "B" };

10

没有使用LINQ的重复操作:

float[] floats = System.Array.ConvertAll(new float[16], v => 1.0f);

6
int[] array = new int[4]; 
array[0] = 10;
array[1] = 20;
array[2] = 30;

或者

string[] week = new string[] {"Sunday","Monday","Tuesday"};

或者

string[] array = { "Sunday" , "Monday" };

在多维数组中。
    Dim i, j As Integer
    Dim strArr(1, 2) As String

    strArr(0, 0) = "First (0,0)"
    strArr(0, 1) = "Second (0,1)"

    strArr(1, 0) = "Third (1,0)"
    strArr(1, 1) = "Fourth (1,1)"

6
您好,最后一块示例代码似乎是Visual Basic的,而问题要求的是C#示例代码。 - Alex KeySmith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接