C# 带有对象初始值设定项的括号

C# 带有对象初始值设定项的括号,c#,constructor,object-initializers,C#,Constructor,Object Initializers,在C#中,我可以有一个类,例如: class MyClass { public void DoStuff(); } 我可以像这样初始化这个类: MyClass mc = new MyClass(); 或: 如果我不需要括号,并且没有要由对象初始值设定项设置的属性,为什么我不能这样做 MyClass mc = new MyClass; 因为语法newmyclass{}是新的无参数构造函数语法,所以可以省略()。构造函数方法public MyClass()通过推理调用 但是,这种语法new

在C#中,我可以有一个类,例如:

class MyClass {
  public void DoStuff();
}
我可以像这样初始化这个类:

MyClass mc = new MyClass();
或:

如果我不需要括号,并且没有要由对象初始值设定项设置的属性,为什么我不能这样做

MyClass mc = new MyClass;

因为语法
newmyclass{}
是新的无参数构造函数语法,所以可以省略
()
。构造函数方法
public MyClass()
通过推理调用

但是,这种语法
newmyclass
很糟糕,因为编译器不接受它是有效的


这并不是说他们做不到,他们可以用编译器做任何事情,但他们没有做到。

因为MyClass是类名/类型,MyClass()是构造函数;您需要(想要)调用的是构造函数。

您无法执行
MyClass mc=new MyClass
,因为该语言解析器的设计者决定不允许您执行此操作。事实上,他们非常慷慨地允许使用一对空的花括号:我想对他们来说,这样做比明确要求至少一个表达式更容易


您所建议的
表达式的结构中没有任何固有的东西会禁止这种语法:修改解析器以支持第三种选择不会花费太多精力。但是,这样做会与调用没有参数的非构造函数方法产生不一致。目前,省略括号会使它们成为在某些上下文中启用特定语义的方法组。很难修改解析器,使其不允许没有括号的参数方法调用,因为它没有语法标记(请注意,当您调用构造函数时,
new
关键字起到了这样一个标记的作用)。

这是因为您正在为要初始化的对象调用默认构造函数。这就是为什么,您使用:

MyClass mc = new MyClass();
您可以尝试,如果不存在默认构造函数(接受零个参数),此行将给出一个错误,类似于“不存在默认构造函数”

考虑一下:

public class MyClass {

    public int Value { get; private set; }

    public MyClass With(int i) {
        Value = i;
        return this;
    }
}

MyClass my = new MyClass().With(5);    // Old-school
MyClass my1 = new MyClass { }.With(6); // Kind of funky looking, but okay.
MyClass my2 = new MyClass.With(4);     // This looks just like a static method call except for the new

OP在他的问题中也说了同样的话。@KeithPayne,这也是答案。编译器根本不支持这种语法。也许您需要
Scala
。你可以省略任何函数的构造函数上不需要的括号,它不带任何参数。@ Caluoux C++让你做同样的事情。P@KChaloux你是对的,C++让你只为构造函数做它,因为有
new
关键字告诉编译器发生了什么。如果你有大括号,你可以省略括号,这让我很惊讶。当我能够区分代码执行(您需要()来调用方法)和变量访问(字段或属性不需要()时,我很高兴。最后一种语法在这方面是可怕的。是的,我写了
newmyclass(){Number=1}
+1,虽然这并没有回答“他们为什么这样设计语言?”这个隐含的问题,但我自己想不出这个问题的答案。。。最好的猜测是,为了识别对方法的引用,为了知道如何查看v表,解析器需要查看Parenethes,但随后,他们必须添加代码来识别同一事物的大括号。@CharlesBretana我确实想知道这个问题的答案,但是我觉得关闭Votest可能会引发一个问题要想真正了解原因,你必须联系C语言设计团队。更有趣的问题是:你为什么想知道?@CodeCaster Simple。设计C#的人很聪明。这似乎是多余的语法,特别是考虑到C++可以做到这一点。我很好奇,希望能喂饱我的强迫症。@RGrapham,我认为这是一个很好的问题,但我不知道答案。
new
应该足以让解析器确定下一个字符串标记应该作为要实例化的类型的名称进行检查,因此我认为只有原始语言设计者才能回答(Eric Gunnersen、Anders Hejlsberg where are are you?、甚至可能是Kernigan/Ritchie?)C但您已经声明了
new
,所以我马上就知道您已经实例化了一个实例。
public class MyClass {

    public int Value { get; private set; }

    public MyClass With(int i) {
        Value = i;
        return this;
    }
}

MyClass my = new MyClass().With(5);    // Old-school
MyClass my1 = new MyClass { }.With(6); // Kind of funky looking, but okay.
MyClass my2 = new MyClass.With(4);     // This looks just like a static method call except for the new