ChatGPT解决这个技术问题 Extra ChatGPT

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

C# 可以使用的所有数组初始化语法是什么?


A
Anthony Pegram

这些是简单数组的当前声明和初始化方法。

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" }; // created populated array of length 2

请注意,还有其他获取数组的技术,例如 IEnumerable<T> 上的 Linq ToArray() 扩展。

另请注意,在上面的声明中,前两个可以将左侧的 string[] 替换为 var (C# 3+),因为右侧的信息足以推断出正确的类型。第三行必须按显示写,因为仅数组初始化语法不足以满足编译器的要求。第四个也可以使用推理。因此,如果您对整个简洁性感兴趣,则上述内容可以写成

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 

出于好奇,有人可以解释为什么第 3 行中的初始化表达式不能单独使用(例如传递给方法)或分配给 var 变量吗?
@Ruben9922:有趣的问题。如果数组初始化程序可以产生除数组之外的任何其他内容,那么 var x = {} 不起作用是有道理的,但我不知道那是什么。所以我猜数组初始化器是一种语言特性。如果您将它与new List<string> {"A", "B"}一起使用,它也会产生不同的效果。
是否有任何理由使用 string array = new string[] { "A", "B" }; 而不是 string array = { "A", "B" };?第一个似乎是多余的。
@Lou 语法来自显式指定类型的能力,以防无法自动推断。但当然,在原始字符串类型的情况下,这种符号肯定看起来是多余的
@Ruben9922:有趣的是,Dim a = { "A", "B" } 确实 在 VB.NET 中工作(使用 Option Strict On 和 Option Infer On)并正确地将 String()(C# 中的 string[])推断为数据类型,所以我猜 C# 设计者故意选择不支持这一点。我想在 VB 中实现起来更容易,因为 VB 只使用花括号进行数组初始化(与 C# 不同,C# 到处都有花括号)。在 VB 中,您还可以在返回数组的方法中编写 Return {}
M
Mike Zboray

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 节“数组创建表达式”。


@BoltClock:您提到的第一个语法是“隐式类型数组创建表达式”。第二个是“匿名对象创建表达式”。您没有列出其他两种类似的语法;它们是“对象初始化器”和“集合初始化器”。
不完全是 C#“语法”,但我们不要忘记(我个人最喜欢的)Array.CreateInstance(typeof(int), 3)
@Jeffrey:如果我们沿着这条路走,它就会开始变得愚蠢。例如,"1,2,3,4".split(',')
然后对于多维数组,存在像 new int[,] { { 3, 7 }, { 103, 107 }, { 10003, 10007 }, }; 这样的“嵌套”符号,等等 int[,,]int[,,,]、...
@Learning-Overthinker-Confused:你有两匹马。您想知道哪个更快。您是否(1)与马赛跑,或(2)在互联网上询问从未见过马的陌生人他认为哪一匹更快?赛马。你想知道哪个更“高效”吗?首先建立一个可衡量的效率标准;请记住,效率是每单位成本产生的价值,因此请仔细定义您的价值和成本。然后双向编写代码并衡量其效率。用科学来回答科学问题,而不是随机询问陌生人的猜测。
k
kiss my armpit

非空数组

var data0 = 新的 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 = 新的 int[0]

var data7 = new int[] { }

var data8 = new [] { } 和 int[] data9 = new [] { } 不可编译。

var data10 = { } 不可编译。请改用 int[] data11 = { }。

作为方法的参数

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

Foo(新的 int[2])

Foo(新 int[2] { 1, 2 })

Foo(新 int[] { 1, 2 })

Foo(新[] { 1, 2 })

Foo({ 1, 2 }) 不可编译

Foo(新的 int[0])

Foo(新的 int[] { })

Foo({}) 不可编译


将无效语法与有效语法更清楚地分开会更好。
给定的例子是否完整?还有其他情况吗?
A
Atomosk
Enumerable.Repeat(String.Empty, count).ToArray()

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


是的,在 var arr1 = Enumerable.Repeat(new object(), 10).ToArray(); 中,您获得了对同一对象的 10 个引用。要创建 10 个不同的对象,您可以使用 var arr2 = Enumerable.Repeat(/* dummy: */ false, 10).Select(x => new object()).ToArray(); 或类似的。
R
Rey
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 这是一个普通的数组:)
@grooveplex 这是一个匿名类型的数组。匿名类型包含字符串类型的成员名称和字符串[] 类型的电话号码。类型由编译器推断。
我打过电话,杨先生说冯先生2018年搬走了
R
Rey

如果您想初始化预先初始化的相等(非 nulldefault 以外)元素的固定数组,请使用:

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

也请参与this讨论。


C
Community

创建自定义类数组的示例

下面是类定义。

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"
    }
};

P
Peter Mortensen

在没有 LINQ 的情况下重复:

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

Y
Yousha Aleayoub

只是一个注释

以下数组:

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" };

B
Brad Larson
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)"

嗨,最后一组示例似乎是 Visual Basic,问题要求提供 c# 示例。
P
Pavneet_Singh
For Class initialization:
var page1 = new Class1();
var page2 = new Class2();
var pages = new UIViewController[] { page1, page2 };

N
Nick Alexeev

另一种创建和初始化对象数组的方法。这类似于 example which @Amol has posted above,除了这个使用构造函数。一点多态性洒进来,我无法抗拒。

IUser[] userArray = new IUser[]
{
    new DummyUser("abc@cde.edu", "Gibberish"),
    new SmartyUser("pga@lna.it", "Italian", "Engineer")
};

上下文类:

interface IUser
{
    string EMail { get; }       // immutable, so get only an no set
    string Language { get; }
}

public class DummyUser : IUser
{
    public DummyUser(string email, string language)
    {
        m_email = email;
        m_language = language;
    }

    private string m_email;
    public string EMail
    {
        get { return m_email; }
    }

    private string m_language;
    public string Language
    {
        get { return m_language; }
    }
}

public class SmartyUser : IUser
{
    public SmartyUser(string email, string language, string occupation)
    {
        m_email = email;
        m_language = language;
        m_occupation = occupation;
    }

    private string m_email;
    public string EMail
    {
        get { return m_email; }
    }

    private string m_language;
    public string Language
    {
        get { return m_language; }
    }

    private string m_occupation;
}

g
gehbiszumeis

对于以下课程:

public class Page
{

    private string data;

    public Page()
    {
    }

    public Page(string data)
    {
        this.Data = data;
    }

    public string Data
    {
        get
        {
            return this.data;
        }
        set
        {
            this.data = value;
        }
    }
}

您可以如下初始化上述对象的数组。

Pages = new Page[] { new Page("a string") };

希望这可以帮助。


l
luka

嗨只是添加另一种方式:从此页面:https://docs.microsoft.com/it-it/dotnet/api/system.linq.enumerable.range?view=netcore-3.1

你可以使用这种形式如果你想生成一个指定范围 0 到 9 内的整数序列:

using System.Linq
.....
public int[] arrayName = Enumerable.Range(0, 9).ToArray();

P
Peter Mortensen

您还可以创建动态数组,即您可以在创建数组之前先向用户询问数组的大小。

Console.Write("Enter size of array");
int n = Convert.ToInt16(Console.ReadLine());

int[] dynamicSizedArray= new int[n]; // Here we have created an array of size n
Console.WriteLine("Input Elements");
for(int i=0;i<n;i++)
{
     dynamicSizedArray[i] = Convert.ToInt32(Console.ReadLine());
}

Console.WriteLine("Elements of array are :");
foreach (int i in dynamicSizedArray)
{
    Console.WriteLine(i);
}
Console.ReadKey();

u
unsafePtr

带有表达式的简单解决方案。请注意,使用 NewArrayInit 您可以只创建一维数组。

NewArrayExpression expr = Expression.NewArrayInit(typeof(int), new[] { Expression.Constant(2), Expression.Constant(3) });
int[] array = Expression.Lambda<Func<int[]>>(expr).Compile()(); // compile and call callback

V
Vikash Rathee

要初始化一个空数组,它应该是 dotnet 5.0 中的 Array.Empty<T>()

对于字符串

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

对于号码

var items = Array.Empty<int>();

C
Chaos Crafter

另一种方法是调用静态函数(用于静态对象)或实例对象的任何函数。这可用于成员初始化。

现在我还没有测试所有这些,所以我会把我测试过的(静态成员和静态函数)

Class x {
    private static Option[] options = GetOptionList();
    private static Option[] GetOptionList() {

        return (someSourceOfData).Select(dataitem => new Option()
                 {field=dataitem.value,field2=dataitem.othervalue});
    }
}

我很想知道是否有办法绕过函数声明。我知道在这个例子中它可以直接使用,但假设函数稍微复杂一点,不能简化为单个表达式。

我想像下面这样(但它不起作用)

Class x {
    private static Option[] options = () => {
        Lots of prep stuff here that means we can not just use the next line
        return (someSourceOfData).Select(dataitem => new Option()
                 {field=dataitem.value,field2=dataitem.othervalue});
    }
}

基本上是一种仅声明填充变量范围的函数的方法。如果有人可以告诉我如何做到这一点,我会很高兴。