2010-05-22 2 views
3

Я преподаю PowerShell, написав простой парсер. Я использую класс .Net framework Collections.Stack. Я хочу изменить объект в верхней части стека на месте.Powershell/.Net: Получить ссылку на объект, возвращенный методом

Я знаю, что могу удалить объект, изменить его, а затем push() его снова, но это поражает меня как неэлегантного.

Во-первых, я попытался это:

$stk = new-object Collections.Stack 
$stk.push((,'My first value')) 
($stk.peek()) += ,'| My second value' 

Который бросил ошибку:

Assignment failed because [System.Collections.Stack] doesn't contain a settable property 'peek()'. 
At C:\Development\StackOverflow\PowerShell-Stacks\test.ps1:3 char:12 
+ ($stk.peek <<<<()) += ,'| My second value' 
    + CategoryInfo   : InvalidOperation: (peek:String) [], RuntimeException 
    + FullyQualifiedErrorId : ParameterizedPropertyAssignmentFailed 

Далее я попытался это:

$ary = $stk.peek() 
$ary += ,'| My second value' 
write-host "Array is: $ary" 
write-host "Stack top is: $($stk.peek())" 

Что помешало ошибку, но до сих пор не сделал Правильная вещь:

Array is: My first value | My second value 
Stack top is: My first value 

Очевидно, что присвоение $ ary - это экземпляр объекта в верхней части стека, поэтому, когда я объект в $ ary, объект в верхней части стека остается неизменным.

Наконец, я прочитал на Дэ [исх] типа, и попытался это:

$ary_ref = [ref]$stk.peek() 
$ary_ref.value += ,'| My second value' 
write-host "Referenced array is: $($ary_ref.value)" 
write-host "Stack top is still: $($stk.peek())" 

Но до сих пор нет кости:

Referenced array is: My first value | My second value 
Stack top is still: My first value 

Я предполагающие метод peek() возвращает ссылку на фактическое объект, а не клон. Если это так, то ссылка, по-видимому, заменяется клоном логикой обработки выражения PowerShell.

Может ли кто-нибудь сказать мне, есть ли способ сделать то, что я хочу? Или мне нужно вернуться к pop()/modify/push()?

ответ

2

Массив всегда имеет фиксированный размер. Когда вы добавляете элемент в массив, создается новый массив с увеличенной длиной и старый массив копируется в новый. Ссылка косвенно изменилась, поэтому у вас есть целый новый массив с 2 элементами, тогда как стек все еще содержит старую. Вместо этого используйте список.

1

Я понял. Это был оператор «+ =», который создавал копию. Кажется, что вы не можете добавлять элементы в массив .Net. Если я использую другой тип объекта, как Hashtable, у меня нет никаких проблем при добавлении элементов в месте:

$stk.push(@{"1"="My first value"}) 
$stk.peek()["2"]="| My second value" 
write-host "Stack top keys: $($stk.peek().keys)" 
write-host "Stack top values: $($stk.peek().values)" 

что дает

Stack top keys: 1 2 
Stack top values: My first value | My second value 

Или для более массивов как объекта, Collections.ArrayList работает

$item = new-object Collections.ArrayList 
$stk.push($item) 
$stk.peek().Add("My first value") 
$stk.peek().Add("| My second value") 
$obj = $stk.peek() 
$obj.Add("| My third value") 
write-host "Stack top is: $($stk.peek())" 

Какие выходы

Stack top is: My first value | My second value | My third value 
Смежные вопросы