Count属性如何在Powershell中运行?

Jer*_*oen 13 powershell

我做了一个非常不幸的错字,花了我相当宝贵的时间:

$errors.Count
Run Code Online (Sandbox Code Playgroud)

0即使存在错误,也会返回" ",因为变量名称应该是单数.这确实有效:

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

但是,我现在想知道为什么$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"
Run Code Online (Sandbox Code Playgroud)

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

$true.Count                   # Will output "1"
$false.Count                  # Will output "1"
Run Code Online (Sandbox Code Playgroud)

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

  1. 数组(如)变量,其中.Count将输出项目数.
  2. 不存在的变量,.Count输出"0".
  3. 声明变量,.Count输出"1".
  4. 内置变量,.Count输出"1".

案例2,3和4对我没有任何意义(还).这里发生了什么?这记录在哪里?该.Count物业如何运作?

Jas*_*irk 16

从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*) { $_ }
Run Code Online (Sandbox Code Playgroud)

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

foreach ($item in $null) { $_ }
Run Code Online (Sandbox Code Playgroud)

也永远不会进入循环.

for语句是迭代结果的另一种方式,例如

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

在这个例子中,$ result中有多少个对象并不重要,循环工作正常.请注意,在V1/V2中,你会写:

$results = @(dir nosuchfile*)
Run Code Online (Sandbox Code Playgroud)

这可以确保$ results是一个数组,但是这种语法很难看,很多人都会忘记它,因此更改以支持Count/Length的方式稍微宽松一些.

  • 我是PowerShell团队的开发人员,实现了这一点,所以忽略了错误的记忆,我的回答是尽可能权威的. (5认同)

Dav*_*ant 6

为了补充Paul的答案,这可能与扩展类型数据有关.引用文档的相关部分:

扩展类型数据定义Windows PowerShell中对象类型的其他属性和方法("成员").您可以扩展Windows PowerShell支持的任何类型,并使用添加的属性和方法,方法与使用在对象类型上定义的属性相同.

和:

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

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

   <Type>
        <Name>System.Array</Name>
        <Members>
            <AliasProperty>
                <Name>Count</Name>
                <ReferencedMemberName>Length</ReferencedMemberName>
            </AliasProperty>
        </Members>
    </Type>
Run Code Online (Sandbox Code Playgroud)

所以我的猜测是,通过提供" .Count"属性,PowerShell假设这是一个数组.