2015-05-22 1 views
1

Ниже показано, что возвращаемый тип отличается от количества возвращенных строк. Почему он разработан таким образом? Очень легко сделать предположение, что он всегда возвращает массив и записывает код $a.Length$a | % { ....}, который будет вызывать ошибку, когда он возвращает только одну строку, если только она не написана как $a = @(invoke-....), что легко забыть.Confused Powershell возвращает тип массива

$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 

И следующий оператор возвращает массив объекта (кстати, почему бы не массив DataRow?)

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

Однако gm возвращает тот же тип для обе переменные. Почему он разработан таким образом, который может быть очень смущен.

Вопрос:

  1. Какой смысл, что массив удаляется, когда только один элемент возвращается?
  2. Почему gm получить тип элемента массива? Как до gm массива?
  3. Почему 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

Хотелось бы, чтобы я мог ответить на этот вопрос, но я думаю, что мне не хватает ключевых ключей. 1. Это может быть до 'Invoke-Sqlcmd', а также зависит от вашей версии PowerShell. 2. Get-Member действует на элементы, переданные в трубе, а не на весь объект, поэтому 3. возвращает то, что он делает. – Matt

+0

Какую версию PowerShell вы используете? – briantist

ответ

2
  1. Большую часть времени в PowerShell, функции/командлеты, которые возвращают объекты, просто возвращают объект. Если требуется вернуть более одного объекта, функция просто вернет объекты до тех пор, пока они не будут выполнены. PowerShell обрабатывает все возвращенные объекты и дает вам массив.
  2. gm - это псевдоним для Get-Member. Когда вы вызываете его по трубопроводу $a | gm, вы вызываете его как конвейер. В этом случае каждый объект в $a равен отдельно, переданному в Get-Member, поэтому он возвращает тип отдельных объектов. Если они все одинаковые, то они будут отображаться только один раз, но на самом деле они проверяют их все. Вы можете предотвратить это, вызвав Get-Member -InputObject $a, который должен показать вам тип массива, если он является массивом.
  3. Как и выше, .GetType() получает тип любого объекта, на который он вызван, поэтому, если это массив, он возвращает это; он не смотрит на отдельные элементы.

Я также хочу отметить, что % (ForEach-Object) и foreach() прекрасно работают, когда не используется массив: "hello" | % { $_ }, как это делает foreach($msg in "hello") { $msg }.

Для решения проблемы $a.Length не работает, когда возвращаемое значение является единственным объектом, это зависит от версии вашей PowerShell.

В версии 2, вы увидите поведение, которое вы видите: вы должны обернуть его в массив первой, или тест на массив с чем-то вроде:

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

Но, powershell 3+, вы можете сделать $a.Length, даже если $a - это всего лишь некоторый объект, а не массив. Он вернется 1. Длина может не отображаться в автозаполнении или в intellisense, но она будет работать.

+0

Для '$ a | % {...} ', я имел в виду' $ a.Length'. Я обновил вопрос. – ca9163d9

+0

@ dc7a9163d9 какая версия powershell? – briantist

+0

Версия 3 и 2. – ca9163d9