2015-02-25 1 views
1

This Q&A установил, что трубопровод powershell иногда разворачивает некоторые коллекции. Предположим, что у нас есть функция, которая испускает коллекцию, которая может быть развернута, но мы не хотим, чтобы конвейер выполнял разворот. Вот пример, демонстрирующий нежелательное разворачивание:Есть ли способ для вызывающего пользователя получить выход функции powershell, не подвергая его (возможному) разворачиванию трубопровода?

Function EmitStack{ 
    [Cmdletbinding()] 
    param() 
    process{[System.Collections.Stack]@(10,20,30)} 
} 

$stack = [System.Collections.Stack]@(10,20,30) 
$stack.GetType() 
$EmittedStack = EmitStack 
$EmittedStack.GetType() 

#Name  BaseType                     
#----  -------- 
#Stack  System.Object 
#Object[] System.Array 

Что мы хотим, чтобы это $EmittedStack переменная содержит чистейший, нетронутый [System.Collections.Stack] объект, функция помещает в трубопроводе. Вместо этого он содержит развернутые элементы стека, повторно свернутые в массив. Есть ли способ, чтобы вызывающий мог получить исходный объект, не подвергая его разворачиванию трубопровода PowerShell (и повторной прокатке)?


Разъяснение: Этот вопрос о ли абонент может получить чистейший объект, даже если он не был завернутыми в жертвенном массиве с помощью функции, прежде чем он ставит его в трубопроводе. Другими словами, я ищу решение, которое не связано с изменением функции.

Причина: Какие типы раскатали является not clearly defined in powershell что предполагает более высокую степень непредсказуемости от системы к системе, PowerShell-версия для Powershell-версии, Dotnet-версии к Dotnet-версии, и т.д. В случае, например, некоторые конвейеры среды powershell Environment неожиданно разворачиваются [System.Collections.Generic.Dictionary] (помните, что для этого нет никаких документированных правил), это помогло бы вызывающему абоненту иметь возможность компенсировать по мере необходимости без необходимости копать код вызываемого абонента.

+0

Я не уверен, что понимаю вашу озабоченность. Обычно разворачивание полезно. Как функция не будет знать, что она вернет то, что будет подвержено нежелательной разворачиванию? Другими словами, почему было бы неприемлемо изменить функцию? Как вызывающий, так и вызывающий должны знать, что они ожидают одного объекта, чтобы вызывающий пользователь мог снова развернуть, если захочет. –

+0

Это только проблема, если выполняются оба следующих условия: 1.Окружение powershell изменилось так, что теперь трубопровод разворачивает типы, которые он ранее не разворачивал. 2. Этот тип испускается непрозрачным источником, как сторонняя или встроенная библиотека Microsoft. – alx9r

+0

Powershell - это язык сценариев, и они подчеркивают производительность по надежности. Если вам нужны надежные результаты, убедитесь, что ваши скрипты работают в совершенно стабильной среде. Вы можете принудительно настроить определенную версию Powershell с помощью переключателя '-version', которого должно быть достаточно, чтобы неожиданно это произошло. Конечно, это означает, что тестирование скриптов в новой версии может быть сложной задачей, но это не общий сценарий (если он не сломался, не обновляйте его). –

ответ

2

Powershell только разворачивает раз. Таким образом, стандартный метод для захвата результат в массиве один пункт, который будет получить развернутый и дать вам обратно исходный объект:

Function EmitStack{ 
    [Cmdletbinding()] 
    param() 
    process{(,[System.Collections.Stack]@(10,20,30))} 
} 

Обратите внимание на (,item) трюк.

Edit: нет никакого способа для вызывающего абонента, чтобы получить исходный объект после разворачивания - Powershell не поддерживает какой-то специальный псевдо-переменной, которая содержит контент до его раскатали. После разворота он был бы неотличим от обычного перечислимого. Хотя вы могли бы разработать решения, которые вообще обходят трубопровод (передают параметры и присваивают свойство, а может быть, становятся очень творческими с закрытием), изменение функции было бы неизбежным.

Как отмечает @Matt, если вызывающий абонент знает, какой тип он должен вернуть (вернее, если вызывающий хочет убедиться, что он всегда является конкретным типом), он всегда может преобразовать результат в желаемый тип, поэтому не имеет значения, будет ли результат развернут или нет. Это все равно не возвращает вам объект, если разворачивание произошло (но, вероятно, очень полезная копия), и предполагается, что Powershell всегда может преобразовать его в тип, если он знает, как разворачивать объекты этого типа, что вероятно, не универсально.

+0

Конечно. Но мои вопросы в том, может ли _caller_ получить исходный объект, если функция не использует ведущую запятую, чтобы обернуть ее в жертвенный массив. – alx9r

+0

Как только он разворачивается, нет возврата. Отправитель должен принять меры предосторожности, чтобы избежать непреднамеренного разворота. –

+0

Ugh. Эта слабо определенная разводка трубопроводов формируется, чтобы стать неприятным источником неопределенного поведения. – alx9r

Смежные вопросы