Gor*_*don 4 powershell class naming-conventions
我注意到但从未见过任何解释的是这个奇怪的小“事实”。我可以从 Powershell 调用的大多数(全部?)类方法都使用 Pascal Case。例如
[System.IO.FileInfo].FullName
$xmlWriter.WriteStartDocument()
[System.GC]::Collect()
Run Code Online (Sandbox Code Playgroud)
还有很多。但我一直看到的一个例外是新的。New(几乎?)总是小写。键入[xml.xmlReaderSettings]::和提供的有用下拉列表是Equals, new& ReferenceEquals。这一直发生,我怀疑这不是巧合,所以我希望有人能解释为什么。我的想法是,由于命名约定是公共方法和参数使用 Pascal Case(而私有方法和参数使用 Camel Case)并且 []::new 既不是属性也不是参数,它间接调用了构造函数,它得到了Camel Case?或者甚至不是 Camel Case,只是小写,在这种情况下看起来是一样的。
我知道在 PowerShell 中这无关紧要,只是好奇底层逻辑是什么。
new小写,因为new很特殊这个答案部分基于我与一些相关方(即 Microsoft 的 PowerShell(前)团队成员)的对话,因此它更多是轶事虚构而不是硬技术事实,但这是一些“他们为什么做 X 而不是 Y”问题的本质
TL;DR:
你的推理是合理的,但它不像微软内部的一个委员会坐下来查看 .NET 规范并决定“如果我们引入合成构造函数调用方法,我们必须打破这些命名约定,本着定义的标准”——与现实生活中的大多数事情一样,决策受到多种因素的影响,我将在下面详述其中的一些因素。
正如你在这个问题指出,new是别人不喜欢-静态成员调用运算符(::)只公开公共静态成员,和.NET命名惯例规定PascalCase“公共成员d名。
但是new打破了这个惯例,并理解为什么你需要查看它在 PowerShell 5.0 中的起源和介绍的上下文
new对象分配关键字的由来new在 PowerShell 上下文中使用名称或关键字直接从C#!
new 作为关键字融入 C# 语言语法,它最著名的应用是通过调用适当的构造函数来实例化新的对象实例:
var instance = new TypeName();
Run Code Online (Sandbox Code Playgroud)
反过来,C#new取自 C++,这是一种服务于类似目的的语言,为类型对象自动分配内存:
T instance = new TypeName;
Run Code Online (Sandbox Code Playgroud)
C++ 反过来new取自 SmallTalk,这是我所知道的最古老的语言,它积极地将它用于对象分配:
instance := TypeName new
Run Code Online (Sandbox Code Playgroud)
The authors of SmallTalk might have used new simply because they thought it fit for purpose, but one could also imagine they took inspiration from ALGOL68 in which I'm given to understand new was a common operator name for array-generating procedures (this part is 100% anecdotal speculation, I've never written or ran any ALGOL).
In any case, using lowercase new to name procedures that allocation objects in memory carries a 50 year legacy.
Before the introduction of this new quasi-method in PowerShell 5.0, the idiomatic way to invoke .NET constructors was to let New-Object handle it:
$instance = New-Object -TypeName 'Target.Type.Name' -ArgumentList @($ctorParamArgs,$go,$here)
Run Code Online (Sandbox Code Playgroud)
New-Object had positional bindings for those two parameters from the initial release in 2.0, in hopes that this new-fangled and shiny, but very verbose, scripting language would appeal to existing users of the .NET ecosystem, particularly developers and sysadmins already familiar with 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
Run Code Online (Sandbox Code Playgroud)
But some developers still felt PowerShell's command expression syntax was too verbose, and before long, script sharing repositories around the internet was littered with scripts that abused the Alias facility to mimic C#:
Set-Alias new New-Object
new TypeName($arg) # doesn't get much closer and this
Run Code Online (Sandbox Code Playgroud)
So new, as a (fake) "constructor keyword", already existed in the community eco system around PowerShell, long before PowerShell 3.0 was even released, and a subset of users clearly yearned for a more concise way to allocate new objects.
class definitionsA major feature in PowerShell 5.0 was the introduction of the enum and class keywords, with which PowerShell users all of a sudden could define their own CTS-compliant data type!
Being able to define new types at runtime is great, but of course you need to be able to use them - so what options are available?
New-Object - can instantiate PowerShell classes just fine, but it feels awkward to have the language itself be able to define types but have no built-in facility for instantiating them.new as a new keyword in the grammar - except, what about compatibility with existing scripts that had abused the alias feature as described in the previous section - should the new new expressions support @() for the argument list?new as a synthetic static member name on type literals - this turned out to be better for compatibility than you might think - New as a member name is an extremely rare occurrence in the .NET ecosystem (Create() being the canonical preference for user-defined constructor wrappers), so the change could be made without altering the language at all - just add special handling in the :: invoke member operator's implementation for when the member name is new.PowerShell 团队最终选择了后者,并决定按照上面讨论的祖先语言的脉络将其保持小写,这反过来会发送您收到的消息 -这个与其他的不同:)