Powershell / .Net:获取对方法返回的对象的引用

发布于 2024-09-02 22:40:43 字数 1631 浏览 6 评论 0原文

我通过编写一个简单的解析器自学 PowerShell。我使用 .Net 框架类 Collections.Stack。我想就地修改堆栈顶部的对象。

我知道我可以 pop() 关闭对象,修改它,然后 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时,栈顶的对象保持不变。

最后,我阅读了 [ref] 类型,并尝试了以下操作:

$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() / 修改 / push() 吗?

I am teaching myself PowerShell by writing a simple parser. I use the .Net framework class Collections.Stack. I want to modify the object at the top of the stack in place.

I know I can pop() the object off, modify it, and then push() it back on, but that strikes me as inelegant.

First, I tried this:

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

Which threw an error:

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

Next I tried this:

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

Which prevented the error but still didn't do the right thing:

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

Clearly, what is getting assigned to $ary is a copy of the object at the top of the stack, so when I the object in $ary, the object at the top of the stack remains unchanged.

Finally, I read up on teh [ref] type, and tried this:

$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())"

But still no dice:

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

I assume the peek() method returns a reference to the actual object, not the clone. If so, then the reference appears to be being replaced by a clone by PowerShell's expression processing logic.

Can somebody tell me if there is a way to do what I want to do? Or do I have to revert to pop() / modify / push()?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

等数载,海棠开 2024-09-09 22:40:44

数组始终具有固定大小。当您向数组添加一项时,会创建一个长度增加的新数组,并将旧数组复制到新数组中。引用已隐式更改,因此您得到了一个包含 2 个元素的全新数组,而堆栈仍包含旧数组。请改用列表。

An array always has a fixed size. When you're adding an item to an array, a new array with an increased length is created and the old array is copied into the new one. The reference has implicitly changed so you've got a whole new array with 2 elements whereas the stack still contains the old one. Use a List instead.

往事随风而去 2024-09-09 22:40:44

我想通了。正是“+=”运算符创建了副本。似乎无法将元素添加到 .Net 数组中。如果我使用不同类型的对象(例如哈希表),我可以毫无困难地添加元素:

$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)"

Which 产生

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())"

Which 输出

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

I figured it out. It was the "+=" operator that was creating the copy. It seems that you can't add elements to a .Net array. If I use a different type of object, like a hashtable, I have no trouble adding elements in place:

$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)"

Which yields

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

Or for a more array-like object, Collections.ArrayList works

$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())"

Which outputs

Stack top is: My first value | My second value | My third value
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文