为什么我可以使用 [pscustomobject] 而不是 [System.Management.Automation.PSCustomObject] 创建对象?

How come I can create objects with [pscustomobject] but not [System.Management.Automation.PSCustomObject]?

为什么我可以使用类型加速器 [pscustomobject] 而不是其全名 [System.Management.Automation.PSCustomObject] 创建对象?是否有一些我没有访问的神奇构造函数?

$a = [pscustomobject]@{name='joe'}
$a.gettype().fullname
System.Management.Automation.PSCustomObject

[System.Management.Automation.PSCustomObject]@{name='joe'}
InvalidArgument: Cannot convert the "System.Collections.Hashtable" value of type "System.Collections.Hashtable" to type "System.Management.Automation.PSCustomObject".

或者我可以尝试 [System.Management.Automation.PSObject],但我只得到一个哈希表:

[psobject].Assembly.GetType('System.Management.Automation.TypeAccelerators')::get.pscustomobject.fullname
System.Management.Automation.PSObject

[System.Management.Automation.PSObject]@{name='joe'}                                                     

Name                           Value
----                           -----
name                           joe

受此主题启发:https://powershell.org/forums/topic/type-accelerator

Is there some magical constructor I'm not accessing?

不,编译器中有神奇的调味料 - 每当 PowerShell 编译器看到右侧是字典且类型字面量具有确切名称 pscustomobject 的强制转换表达式时,它会处理字典或哈希表(无论是否为文字)作为有序字典并将其转换为 PSObject.

来自VisitConvertExpression in Compiler.cs

var typeName = convertExpressionAst.Type.TypeName;
var hashTableAst = convertExpressionAst.Child as HashtableAst;
Expression childExpr = null;
if (hashTableAst != null)
{
    var temp = NewTemp(typeof(OrderedDictionary), "orderedDictionary");
    if (typeName.FullName.Equals(LanguagePrimitives.OrderedAttribute, StringComparison.OrdinalIgnoreCase))
    {
        return Expression.Block(
            typeof(OrderedDictionary),
            new[] { temp },
            BuildHashtable(hashTableAst.KeyValuePairs, temp, ordered: true));
    }

    if (typeName.FullName.Equals("PSCustomObject", StringComparison.OrdinalIgnoreCase))
    {
        // pure laziness here - we should construct the PSObject directly.  Instead, we're relying on the conversion
        // to create the PSObject from an OrderedDictionary.
        childExpr = Expression.Block(
            typeof(OrderedDictionary),
            new[] { temp },
            BuildHashtable(hashTableAst.KeyValuePairs, temp, ordered: true));
    }
}

请注意这也是 [ordered]@{Key='Value'} 导致 OrderedDictionary

的方式