Почему вызов блока сценариев Powershell с помощью .Invoke () возвращает коллекцию? - PullRequest
5 голосов
/ 27 января 2012

Кажется, что при вызове блока сценария Powershell (путем вызова метода .Invoke()) всегда создается коллекция. В частности, коллекция типа

System.Collections.ObjectModel.Collection`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]

Даже при вызове пустого блока скрипта ({}.Invoke()) возвращается коллекция. Вызов одного и того же блока сценария с использованием оператора вызова (&) дает обычно ожидаемый результат (либо скаляр, либо [object[]]).

Это оказывается удобным, если вам нужен набор вместо массива, но это кажется противоречивым.

Кто-нибудь знает, почему он так себя ведет?

Edit:

Я знал, что есть два разных вызова, .Invoke() и .InvokeReturnAsIs() от чтения спецификации языка. Вот где я впервые это заметил.

Я просто не понимаю причины, стоящие за соглашением об именах, и то, как его механизм работает. Глядя на документацию, я бы подумал, что метод вызова по умолчанию - это не то, что используется, когда скрипт-блок вызывается в Powershell. Похоже, что .InvokeReturnAsIs() просто возвращает поток объектов, а затем Powershell упаковывает его в массив объектов, если имеется более одного объекта, как скалярный, если есть только один объект, или создает нулевой объект, если его нет, как будто неявный конвейер там. Использование .Invoke() всегда возвращает коллекцию, а Powershell оставляет ее как коллекцию.

Ответы [ 3 ]

10 голосов
/ 27 января 2012

Похоже, разница между этими двумя методами:

Invoke - вызывает блок скрипта с указанными аргументами, возвращая результаты в виде объектов PSObject.

InvokeReturnAsIs - Запускает блок скрипта с указанными аргументами.Этот метод возвращает необработанные (развернутые) объекты результата, чтобы он мог быть более эффективным.

http://msdn.microsoft.com/en-us/library/system.management.automation.scriptblock_methods(v=vs.85).aspx

Invoke

$code = {"a"}
$code.Invoke().Gettype().FullName

Вывод:

System.Collections.ObjectModel.Collection`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]

InvokeReturnAsIs

$code.InvokeReturnAsIs().GetType().FullName

Вывод:

System.String
5 голосов
/ 23 ноября 2013

Я предполагаю, что команда хотела соответствовать PowerShell.Invoke() API , который возвращает Collection<PSObject>. Эта сигнатура C # облегчает для клиентов использование возвращаемых значений 0, 1 или N и не беспокоится о проверке на нулевое значение и о том, был ли возвращенный объект обернут или нет.

Из .NET Design Guidelines :

НЕ возвращать нулевые значения из свойств коллекции или из методов возвращающие коллекции. Вернуть пустую коллекцию или пустой массив вместо этого.

Тогда вы можете сказать, почему бы просто не вернуть object. Тогда мне пришлось бы против null или нет, а затем мне пришлось бы проверить, реализовал ли он ICollection, чтобы определить, есть ли у меня скаляр или коллекция. С точки зрения разработчика на C # это изверг (извините за рифму). : -)

1 голос
/ 27 января 2012

Потому что это то, для чего оно предназначено, и есть альтернатива!

Invoke - вызывает блок сценария с указанными аргументами, возвращая результаты в виде (коллекции) объектов PSObject.

InvokeReturnAsIs - Запускает блок скрипта с указанными аргументами. Этот метод возвращает необработанные (развернутые) объекты результата, чтобы он мог быть более эффективным.

Кроме того, {}.invoke() возвращает ноль, поэтому я не знаю, откуда у вас сложилось впечатление, что даже это возвращает коллекцию.

http://msdn.microsoft.com/en-us/library/system.management.automation.scriptblock.invokereturnasis(v=vs.85).aspx

...