为什么 PowerShell [TYPE]::new() 是小写

Why is PowerShell [TYPE]::new() lower case

我注意到但从未见过任何解释的是这个奇怪的小“事实”。 我可以从 Powershell 调用的大多数(全部?)class 方法都使用 Pascal Case。例如

[System.IO.FileInfo].FullName
$xmlWriter.WriteStartDocument()
[System.GC]::Collect()

还有更多。但我一直看到的一个例外是新的。 New 是(几乎?)总是小写的。输入 [xml.xmlReaderSettings]::,提供的有用下拉列表为 EqualsnewReferenceEquals。 这种情况一直发生,我怀疑这不是巧合,所以我希望有人能解释为什么。 我的想法是,由于命名约定是 Public 方法和参数使用 Pascal 大小写(而私有方法和参数使用 Camel 大小写)并且 []::new 既不是 属性 也不是参数,它是对构造函数的间接调用,它有驼峰式大小写吗?或者甚至不是驼峰式大小写,只是小写,在这种情况下看起来是一样的。

我知道在PowerShell中这并不重要,只是好奇底层逻辑是什么。

new 是 lower-case 因为 newspecial

这个答案部分基于我与一些相关方(即 Microsoft 的 PowerShell(前)团队成员)的对话,所以它更多的是轶事虚构这不是硬性的技术事实,但这就是一些“为什么他们做 X 而不是 Y”问题的本质

TL;DR:
您的推理是合理的,但这不像微软内部的一个委员会坐下来查看 .NET 规范并决定“如果我们引入合成构造函数调用方法,我们必须打破这些命名约定,本着定义标准的精神” - 与现实生活中的大多数事情一样,这个决定受到多种因素的影响,我将在下面重述其中的一些。


正如您在问题中指出的那样,new 与其他人不同 - 静态成员调用运算符 (::) 仅公开 public 静态成员,.NET 命名约定为 public 成员规定了 PascalCase 的名称。

但是 new 打破了这一惯例,要理解 为什么 您需要查看它在 PowerShell 5.0

中的起源和介绍的上下文

用于对象分配的 new 关键字的来源

在 PowerShell 上下文中使用名称或关键字 new 直接从 C#!

中取消

new 作为关键字嵌入到 C# 语言语法中,它最 well-known 的应用是通过调用适当的构造函数来实例化新的对象实例:

var instance = new TypeName();

C# 又从 C++ 中获取了 new,C++ 是一种用于类似目的的语言,为类型化对象自动分配内存:

T instance = new TypeName;

C++ 又从 SmallTalk 中获取了 new,这是我所知道的最古老的语言,它积极地将其用于对象分配:

instance := TypeName new

SmallTalk 的作者使用 new 可能只是因为他们认为它符合目的,但也可以想象他们从 ALGOL68 中获得灵感,我在其中理解 new 是array-generating 过程的通用运算符名称(这部分是 100% 的轶事推测,我从未写过或 运行 任何 ALGOL)。

无论如何,使用小写 new 来命名内存中分配对象的过程具有 50 年的历史。

PowerShell <5.0 中的构造函数调用

在 PowerShell 5.0 中引入此 new quasi-method 之前,调用 .NET 构造函数的惯用方法是让 New-Object 处理它:

$instance = New-Object -TypeName 'Target.Type.Name' -ArgumentList @($ctorParamArgs,$go,$here)

New-Object 在 2.0 的初始版本中对这两个参数进行了位置绑定,希望这个 new-fangled 和闪亮的 但非常冗长 ,脚本语言将吸引 .NET 生态系统的现有用户,尤其是已经熟悉 C# 的开发人员和系统管理员:

# Lot's of typing on the keyboard in PowerShell ...
New-Object -TypeName 'TypeName' -ArgumentList @($arg)

# ... compared to C#
new TypeName(arg);

# The compromise - New-Object invoked with positional binding:
New-Object TypeName $arg

但一些开发人员仍然觉得 PowerShell 的命令表达式语法过于冗长,不久之后,互联网上的脚本共享存储库中充斥着滥用 Alias 功能模仿 C# 的脚本:

Set-Alias new New-Object
new TypeName($arg) # doesn't get much closer and this

所以 new,作为一个(假的)“构造函数关键字”,早在 PowerShell 3.0 发布之前就已经存在于围绕 PowerShell 的社区生态系统中,并且一部分用户显然渴望更多分配新对象的简洁方法。

PowerShell 5.0 和 class 定义的出现

PowerShell 5.0 的一个主要功能是引入了 enumclass 关键字,PowerShell 用户突然可以使用它们 定义自己的 CTS-compliant数据类型!

能够在运行时定义新类型很棒,但当然您需要能够使用它们 - 那么有哪些选项可用?

  • New-Object - 可以实例化 PowerShell 类 就好了,但是让 语言本身 能够 定义感觉很尴尬 类型,但没有 built-in 实例化它们的工具。
  • 在语法中引入 new 作为新关键字 - 除了,与上一节中描述的滥用别名功能的现有脚本的兼容性如何 - 如果新的 new 表达式支持@() 参数列表?
  • 引入 new 作为类型文字上的合成静态成员名称 - 事实证明这比你想象的更好的兼容性 - New 作为成员名称在.NET 生态系统(Create() 是 user-defined 构造函数包装器的规范偏好),因此可以在根本不改变语言的情况下进行更改 - 只需在 :: 调用成员运算符的成员名称为 new.
  • 时的实现

PowerShell 团队最终选择了后者,并决定按照上面讨论的祖先语言的风格将其保留为小写,这反过来又发送了您收到的消息 - 这条消息与其他消息不同 :)