使用new关键字时为什么不需要括号?

时间:2012-11-26 20:54:14

标签: c#

如果我想获取某个目录中所有文件的列表,我可以输入类似的内容:

var files = (new DirectoryInfo(@"C:\Temp")).GetFiles();

但是,以下内容也有效(请注意“new”关键字之前缺少括号):

var files = new DirectoryInfo(@"C:\Temp").GetFiles();

为什么允许这种情况发生?声明如下:

2 + 4 * 3   and   (2 + 4) * 3
由于括号,

将分别解析为14和18。

似乎我的代码示例类似于在DirectoryInfo对象的静态版本上调用“.GetFiles()”方法(因为缺少“new”关键字),其中括号与“新的“关键字使我明确表示我正在使用DirectoryInfo对象的实例。

即:

2   +  4               * 3
new    DirectoryInfo()   .GetFiles()

VS

(2   +  4              ) * 3
(new    DirectoryInfo())   .GetFiles()

为什么会出现这种情况,有一个简单的解释吗? C#词法分析器处理这两种情况(有/无括号)不是更有效吗?我的比喻有缺陷吗?

5 个答案:

答案 0 :(得分:8)

  

注意:这个答案有很多表达方式,彼此相同。我没有将它们内联或分成两行,而是采用<==>的简写来表示&#34;相当于&#34;。所以

foo   <==>   bar
     

应该被理解为&#34;表达式foo等同于表达式bar&#34;。

您正在谈论的是优先级*的优先级高于二进制+运算符,因此它&#34;绑定其操作数&#34;更严格。所以:

 x * y + z   <==>   (x * y) + z

new和&#34;点&#34;部分是主要表达式,它们具有相同的优先级。 当两个表单具有相同的优先级时,将涉及 associativity 。当涉及new运算符时,C#规范实际上并不十分清楚,但.运算符是二元运算符,并且所有二元运算符都被认为是 left-缔合。换句话说:

x.y.z   <==>   (x.y).z

另一个例子是,*/具有相同的优先级,因此:

x * y / z   <==>   (x * y) / z
x / y * z   <==>   (x / y) * z

因此:

new DirectoryInfo(x).GetFiles()   <==>   (new DirectoryInfo()).GetFiles()

所有这些都与评估顺序有些分开,评估顺序始终从左到右。例如,在表达式x + y * z中,*的优先级越高意味着:

x + y * z   <==>   x + (y * z)

...但它仍然x首先进行评估,然后是y,然后是z,然后是乘法,最后是加法。正常情况下,Eric Lippert writes extremely well on this topic

答案 1 :(得分:4)

请参阅有关优先级的MSDN上的文章:7.2.1

由于所有非赋值二元运算符都是左关联的,因此从左到右对前同步new.运算符进行求值。

因此,在给定的表达式中,在调用其方法之前对象进行实例化。此外 - new具有等同优先权,因此它会在.获得之前使用类型标识符(从左到右)。

答案 2 :(得分:3)

调用静态方法的语法是DirectoryInfo.GetFiles()而不是DirectoryInfo(...).GetFiles(),因此我不确定这两种解释之间是否存在冲突。

无论哪种方式,具有数值表达式的示例将首先乘以3,因为乘法具有比加法或减法更高的优先级。所有括号都允许您覆盖默认优先级。

即使语法与调用静态方法相同,在您询问的情况下,默认优先级仍然会导致它在没有括号的情况下按预期工作。

答案 3 :(得分:2)

您不能new返回值,因此编译器知道将new添加到初始化类型,并在新实例上运行该方法。

(new A()).Foo() // Makes sense! sort of...
new (A().Foo()) // Makes absolute no sense.

(1 + 4) * 10 // Makes sense
1 + (4 * 10) // Also makes sense

数字与C#关键字之间的协同工作逻辑有所不同。

答案 4 :(得分:1)

你的比喻适用于数学运算的顺序。但是在语法上使用new表示编译器已经为类的“新”实例做好了准备。无论是否括号,您可以使用关键字new来获得该类的新实例。