对象初始化器语法混乱.在初始化程序中使用括号?

bgi*_*uga 1 c# object-initializers

所以我正在查看文档以了解如何使用对象初始化程序,无论是否为匿名类型.我唯一想知道的是为什么(如果重要的话)在这个例子中存在差异.

它是这样的:对于一只猫

class Cat
{
    public int Age { get; set; }
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我可以看到第一个例子:

Cat cat = new Cat { Age = 10, Name = "Fluffy" };
Run Code Online (Sandbox Code Playgroud)

这是有道理的.但是,您可以找到以下内容:

List<Cat> cats = new List<Cat>
{
    new Cat(){ Name = "Sylvester", Age=8 },
    new Cat(){ Name = "Whiskers", Age=2 }
};
Run Code Online (Sandbox Code Playgroud)

现在我的问题是:(为什么)new Cat{...} 和之间存在差异new Cat(){...}?我们为什么要使用(或不使用)括号?

Pac*_*ac0 6

这些只是在 C# 中使用对象初始化实例化对象的两种可接受的等效语法(如果您只是在做,则不能省略括号var cat = new Cat();)。

  • 由于您的类没有显式构造函数,因此向 Cat 类提供了一个默认的无参数构造函数
  • new Cat {...}允许实例化和初始化Cat 对象的属性作为new Cat() {...}调用上述构造函数的快捷方式。

关于构造函数的部分很重要。如果没有隐式默认构造函数/显式无参数构造函数,则不能省略括号,并且无论如何都必须在其中提供参数:

public class Cat {
    public string Name;
    public int Age;

    public Cat(string s) { // since I provide a constructor with parameter here, no parameterless constructor exists
        Name = s; 
    } 
}

// ...
void TestCat() 
{

    // compilation error : 'Cat'' does not contain a constructor that takes 0 arguments
    //var badCat1 = new Cat { Name = "Felix", Age = 3} ;
    //var badCat2 = new Cat() { Name = "Felix", Age = 3} ;

    // works (but no way to remove parenthesis here, since there are parameters to pass to csontructor)
    var goodCat = new Cat("Felix") { Age = 3 } ;

    Console.WriteLine($"The cat {goodCat.Name} is {goodCat.Age} years old");
}
Run Code Online (Sandbox Code Playgroud)

特殊情况:(经常用于集合、列表、字典等......)。

如果类 T 实现了 IEnumerable(即有一个 IEnumerable GetEnumerator() 公共函数),并实现了一个 Add 方法,那么对象初始值设定项将使用 Add 方法和枚举的集合。

示例来自https://blog.mariusschulz.com/2014/06/26/fun-with-custom-c-collection-initializers

创建特殊类“Points”,其作用类似于带有初始化的“List”。

请注意,这也使用了现有的无参数构造函数!

public class Points : IEnumerable<Point3D>
{
    private readonly List<Point3D> _points;

    public Points()
    {
        _points = new List<Point3D>();
    }

    public void Add(double x, double y, double z)
    {
        _points.Add(new Point3D(x, y, z));
    }

    public IEnumerator<Point3D> GetEnumerator()
    {
        return _points.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样使用:

var cube = new Points
{
    { -1, -1, -1 },
    { -1, -1,  1 },
    { -1,  1, -1 },
    { -1,  1,  1 },
    {  1, -1, -1 },
    {  1, -1,  1 },
    {  1,  1, -1 },
    {  1,  1,  1 }
};
Run Code Online (Sandbox Code Playgroud)


Jam*_*iec 5

如果对象具有无参数构造函数,则可以省略括号.所以这两个都是有效的

// Assuming cat has a constructor with no parameters
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
Cat cat = new Cat() { Age = 10, Name = "Fluffy" };
Run Code Online (Sandbox Code Playgroud)

List<T>本身有一个对象初始化器,您可以在其中提供任意数量的项目,它们会自动添加到集合中.

List<Cat> cats = new List<Cat>()
{
    new Cat(){ Name = "Sylvester", Age=8 }, // Add sylvester to the List
    new Cat(){ Name = "Whiskers", Age=2 } // And Whiskers too
};
Run Code Online (Sandbox Code Playgroud)

如上所述,您也可以删除括号

List<Cat> cats = new List<Cat>
{
    new Cat { Name = "Sylvester", Age=8 }, // Add sylvester to the List
    new Cat { Name = "Whiskers", Age=2 } // And Whiskers too
};
Run Code Online (Sandbox Code Playgroud)