【问题标题】:How does the Count property work in Powershell?Count 属性在 Powershell 中如何工作?
【发布时间】:2026-01-13 16:25:02
【问题描述】:

我犯了一个非常不幸的错字,浪费了我不少宝贵的时间:

$errors.Count

这会返回“0”,即使有错误,因为变量名应该是单数。这确实工作:

$error.clear()                # To ensure a correct repro
Copy-Item asdf fdsa           # Will show an error
$error.Count                  # Will output "1"

但是,我现在想知道为什么$errors.Count 给了我任何东西,以及为什么它给了我“0”。于是我继续做了一些测试,得到了如下结果:

$asdf.Count                   # Will output "0"
$nrOfEinsteinsInSpace.Count   # Will output "0"
$a = 0; $a.Count;             # Will output "1"
$b = 2; $a.Count;             # Will output "1"
$x = 1,2,3; $x.Count;         # Will output "3"

并收集更多数据以便能够在这里提出一个明智的问题:

$true.Count                   # Will output "1"
$false.Count                  # Will output "1"

所以我们有以下不同的情况:

  1. Array(like) 变量,其中.Count 将输出项目数。
  2. 不存在的变量,.Count 将输出“0”。
  3. 声明的变量,其中.Count 将输出“1”。
  4. 内置变量,其中.Count 将输出“1”。

案例 2、3 和 4 对我来说没有任何意义(目前)。这里发生了什么?这是在哪里记录的? .Count 属性是如何工作的?

【问题讨论】:

    标签: powershell


    【解决方案1】:

    从 PowerShell V3 开始,属性 Count 和 Length 得到了与扩展类型数据(也称为 ETS 或扩展类型系统)无关的非常特殊的处理。

    如果实例具有 Count/Length 属性,那么一切都会像在 V1/V2 中一样继续工作 - 返回来自实例的值。

    如果实例没有 Count/Length 属性,从 V3 开始,您将返回 1 而不是错误,如果实例为 $null,您将返回 0。如果您已开启严格模式,您会收到类似 V2 中的错误。

    我承认这有点奇怪,但它解决了 cmdlet 返回 0、1 或多个对象时的常见问题。

    通常,您会通过管道或使用 foreach 语句遍历这些结果。例如:

    dir nosuchfile* | % { $_ }
    foreach ($item in dir nosuchfile*) { $_ }
    

    在上面的 foreach 情况下,如果命令没有返回任何值,V2 实际上会进入循环。这在 V3 中进行了更改,以更好地满足人们的期望,但这也意味着:

    foreach ($item in $null) { $_ }
    

    也永远不会进入循环。

    for 语句是另一种遍历结果的方式,例如

    $results = dir nosuchfile*
    for ($i = 0; $i -lt $results.Count; $i++) { $results[$i] }
    

    在这个例子中,$result 中有多少对象并不重要,循环工作得很好。请注意,在 V1/V2 中,您会这样写:

    $results = @(dir nosuchfile*)
    

    这确保了 $results 是一个数组,但这种语法很丑陋,很多人会忘记它,因此以稍微宽容的方式支持 Count/Length。

    【讨论】:

    • 哇,与@DavidBrabant 和 Paul 的其他两个答案完全不同。我很欣赏这两种努力,我不确定我是否有资格决定接受哪个答案。如果我看到 V2 和 V3 之间有类似的差异,明天必须在工作中检查。感谢您的宝贵时间!
    • 我是实现这一点的 PowerShell 团队的开发人员,所以忽略错误的记忆,我的回答是尽可能权威。
    • 请注意,strict 模式仍然会引发错误,正如 Jason 所说!那个让我摸不着头脑……
    • 当迭代函数返回的项目如此复杂时,它肯定会降低人们对 powershell 启用的功能的热情。
    【解决方案2】:

    为了补充 Paul 的回答,这可能与 extended type data 有关。引用文档的相关部分:

    扩展类型数据定义了额外的属性和方法 Windows PowerShell 中对象类型的(“成员”)。您可以扩展任何 Windows PowerShell 支持的类型并使用添加的 以与使用属性相同的方式使用属性和方法 在对象类型上定义。

    还有:

    Windows PowerShell 中有三个扩展类型数据源 会议。 Windows PowerShell 安装目录中的 Types.ps1xml 文件会自动加载到每个 Windows PowerShell 会话中。

    如果您打开该 Types.ps1xml 文件(在 $pshome 中),您会在文件的开头看到:

       <Type>
            <Name>System.Array</Name>
            <Members>
                <AliasProperty>
                    <Name>Count</Name>
                    <ReferencedMemberName>Length</ReferencedMemberName>
                </AliasProperty>
            </Members>
        </Type>
    

    所以我的猜测是,通过提供“.Count”属性,PowerShell 假定这是一个数组。

    【讨论】:

      【解决方案3】:

      我认为它是这样工作的:

      案例 1:在数组中,.Count 属性实际上链接到 .Length 属性,该属性显示数组中的项目数

      案例 2:非存在变量由 powershell 自动创建并使用值 $null 进行初始化

      案例 3 / 4:在这一点上,我不确定为什么会发生这种情况,但由于 String、Int 或布尔对象都没有 .Count 属性,我可以想象该属性是由父对象继承的。

      该行为表明该变量被视为数组,因此分配了 1 值的输出将为 1,没有值的结果将为 0。

      编辑: 为了完整起见,这里是文档的链接:Technet,谢谢@David Brabant

      【讨论】: