简体   繁体   English

困惑的Powershell返回的数组类型

[英]Confused Powershell returned array type

The following shows that the returned type are different depends on how many rows returned. 以下显示返回的类型不同,取决于返回的行数。 Why it's designed this way? 为什么这样设计? It's very easy to make assumption it always returns an array and write the code $a.Length $a | % { ....} 这很容易使假设它总是返回一个数组,编写代码$a.Length $a | % { ....} $a | % { ....} which will raise error when it returns only one row, unless the it's written as $a = @(invoke-....) , which is easy to forget. $a | % { ....}仅返回一行时会引发错误,除非它写为$a = @(invoke-....) ,这很容易忘记。

$a=Invoke-Sqlcmd -ServerInstance server "select 1 a"
$b=Invoke-Sqlcmd -ServerInstance server "select 1 a union all select 2"
$a.GetType()
IsPublic IsSerial Name                                     BaseType
    -------- -------- ----                                     --------
    True     False    DataRow                                  System.Object

And the following statement returns an array of object (BTW, why not an array of DataRow?) 下面的语句返回一个对象数组(顺便说一句,为什么不是DataRow数组?)

$b.GetType()
IsPublic IsSerial Name                                     BaseType
    -------- -------- ----                                     --------
    True     True     Object[]                                 System.Array

However, gm returns the same type for both variables. 但是, gm为两个变量返回相同的类型。 Why it's designed this way which can be very confused. 为什么以这种方式设计,这可能会非常混乱。

Question: 题:

  1. What's the point that the array is removed when only one item is returned? 仅返回一项时删除数组的意义是什么?
  2. Why gm get item type of an array? 为什么gm获取数组的项目类型? How to gm of an array? 如何gm的数组?
  3. Why getType() cannot return the data type of the item when it returns an array type? 为什么getType()返回数组类型时不能返回该项目的数据类型?

?

PS SQLSERVER:\> $a|gm


   TypeName: System.Data.DataRow

Name              MemberType            Definition
----              ----------            ----------
AcceptChanges     Method                void AcceptChanges()
......
ToString          Method                string ToString()
Item              ParameterizedProperty System.Object Item(int columnIndex) {get;set;}, System.Object Item(string co...
a                 Property              int a {get;set;}


PS SQLSERVER:\> $b|gm


   TypeName: System.Data.DataRow

Name              MemberType            Definition
----              ----------            ----------
AcceptChanges     Method                void AcceptChanges()
......
ToString          Method                string ToString()
Item              ParameterizedProperty System.Object Item(int columnIndex) {get;set;}, System.Object Item(string co...
a                 Property              int a {get;set;}
  1. Most of the time in PowerShell, functions/cmdlets that return objects, simply return the object. 在PowerShell中,大多数时候,返回对象的函数/ cmdlet只是返回对象。 If more than 1 object is to be returned, the function just keeps returning objects until it's done. 如果要返回多个对象,该函数将一直保持返回对象,直到完成。 PowerShell handles all of the returned objects and gives you an array. PowerShell处理所有返回的对象并为您提供一个数组。
  2. gm is an alias for Get-Member . gmGet-Member的别名。 When you call it by piping to it $a | gm 通过管道调用它时$a | gm $a | gm , you are invoking it as a pipeline. $a | gm ,您将其作为管道调用。 In this case, each object in $a is individually passed to Get-Member , so it returns the type of the individual object(s). 在这种情况下, $a每个对象都单独传递给Get-Member ,因此它返回单个对象的类型。 If they are all the same, then it will only display it once, but it's actually checking all of them. 如果它们都相同,则只会显示一次,但实际上是在检查所有这些。 You can prevent this by calling Get-Member -InputObject $a which should show you the array type if it is an array. 您可以通过调用Get-Member -InputObject $a来防止这种情况,如果它是一个数组,则应显示数组类型。
  3. Similar to the above, .GetType() gets the type of whatever object it's invoked on, so if it's an array, then it returns that; 与上面的类似, .GetType()获取调用它的对象的类型,因此,如果它是一个数组,则返回该对象。 it's not looking at the individual elements. 它不是在看单个元素。

I also want to point out that % ( ForEach-Object ) and foreach() work fine when not used on an array: "hello" | % { $_ } 我也想指出的是, %ForEach-Object )和foreach()在阵列上没有使用正常工作: "hello" | % { $_ } "hello" | % { $_ } , as does foreach($msg in "hello") { $msg } . "hello" | % { $_ } ,就像foreach($msg in "hello") { $msg }

To address the issue of $a.Length not working when the return value is a single object, it depends on your powershell version. 要解决$a.Length在返回值是单个对象时不起作用的问题,这取决于您的Powershell版本。

In version 2, you will see the behavior you are seeing: you'll have to wrap it in an array first, or test for an array with something like: 在版本2中,您将看到所看到的行为:您必须首先将其包装在一个数组中,或者使用类似以下内容的数组进行测试:

if ($a -is [Array]) {
    $itemCount = $a.Length
} else {
    $itemCount = 1
}

But, in powershell 3+, you can do $a.Length even if $a is just some object and not an array. 但是,在Powershell 3+中,即使$a只是某个对象而不是数组,也可以执行$a.Length It will return 1. Length may not show up in autocomplete or in intellisense, but it will work. 它将返回1。长度可能不会显示在自动完成或智能提示中,但可以使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM