因此,我尝试查找该问题的答案,发现通常可用的答案是PowerShell按值传递参数。这些普遍接受的解决方案均张贴示例代码以证明其断言,类似于以下内容:
Function add1 ($parameter)
{
Write-Host " In Function: `$parameter = $parameter"
Write-Host " In Function: `$parameter += 1"
$parameter += 1
Write-Host " In Function: `$parameter = $parameter"
}
cls
$a = 1
Write-Host "Before function: `$a = $a"
add1 $a
Write-Host " After function: `$a = $a"
结果如下:
Before function: Run Command: $a = 1
In Function: $parameter: 1
In Function: Run Command: $parameter += 1
In Function: $parameter: 2
After function: $a: 1
从而证明参数是通过值传递的,对吧?好吧,我几乎没有时间对正在编写的功能进行故障排除。该函数向传递给该函数的PSCustomObject中添加了几个其他NoteProperty项,并且即使我没有在父作用域中修改原始对象,我的程序也会抛出各种错误,指出NoteProperty已经存在。在函数内部。
因此,我设置了上述代码的一个版本,以使用[PSCustomObject]类型的参数进行测试,如下所示:
Function F1($Obj)
{
'Function F1: Run command: $Obj.FirstValue = 11'
$Obj.FirstValue = 11
" `$Obj.Name: $($StartObject.Name)"
" `$Obj.FirstValue: $($StartObject.FirstValue)"
" `$Obj.SecondValue: $($StartObject.SecondValue)"
}
Function F2($Obj)
{
'Function F2: Run command: $Obj | Add-Member -MemberType NoteProperty -Name SecondValue -Value 33'
$obj | Add-Member -MemberType NoteProperty -Name SecondValue -Value 33
" `$Obj.Name: $($StartObject.Name)"
" `$Obj.FirstValue: $($StartObject.FirstValue)"
" `$Obj.SecondValue: $($StartObject.SecondValue)"
}
cls
Remove-Variable StartObject
"Main script: Run command: `$StartObject = [PSCustomObject]@{Name='Original';FirstValue=22}"
$StartObject = [PSCustomObject]@{Name='Original';FirstValue=22}
" `$StartObject.Name: $($StartObject.Name)"
" `$StartObject.FirstValue: $($StartObject.FirstValue)"
" `$StartObject.SecondValue: $($StartObject.SecondValue)"
'Run command: F1 $StartObject'
" "
F1 $StartObject
" "
"Main script: `$StartObject.Name: $($StartObject.Name)"
" `$StartObject.FirstValue: $($StartObject.FirstValue)"
" `$StartObject.SecondValue: $($StartObject.SecondValue)"
"Run command: F2 $StartObject"
" "
F2 $StartObject
" "
"Main script: `$StartObject.Name = $($StartObject.Name)"
" `$StartObject.FirstValue = $($StartObject.FirstValue)"
" `$StartObject.SecondValue = $($StartObject.SecondValue)"
这个凌乱的编程片段产生以下输出:
Main script: Run command: $StartObject = [PSCustomObject]@{Name='Original';FirstValue=22}
$StartObject.Name: Original
$StartObject.FirstValue: 22
$StartObject.SecondValue:
Run command: F1 $StartObject
Function F1: Run command: $Obj.FirstValue = 11
$Obj.Name: Original
$Obj.FirstValue: 11
$Obj.SecondValue:
Main script: $StartObject.Name: Original
$StartObject.FirstValue: 11
$StartObject.SecondValue:
Run command: F2 @{Name=Original; FirstValue=11}
Function F2: Run command: $Obj | Add-Member -MemberType NoteProperty -Name SecondValue -Value 33
$Obj.Name: Original
$Obj.FirstValue: 11
$Obj.SecondValue: 33
Main script: $StartObject.Name = Original
$StartObject.FirstValue = 11
$StartObject.SecondValue = 33
这些结果清楚地表明,当使用[PSCustomObject]参数时,函数内的任何修改都将在传递的对象上进行,从而通过引用传递。无论将我的参数定义为[PSCustomObject] $ Obj,还是不键入任何参数,都会发生此行为。这本身并不是一个大问题,但是问题是,在我浏览的任何文档中我都找不到如此小的信息。我检查了一些教程站点和有关函数参数的Microsoft自己的文档,但是没有看到此异常。
因此,我的问题可以归结为:有没有人找到任何文档来支持我的理论,即尽管大多数参数默认为按值传递,但在涉及对象时它们是通过引用传递的?
我非常愿意相信我在某处错过了一些文档,所以请...指出并向我展示我的方式中的错误!:)
非常感谢
注:以下也适用于分配一个变量到另一个:$b = $a
...
*品牌$b
引用相同的对象是$a
不如果$a
的值是一个实例引用类型,
*品牌$b
收到一个独立的副本中$a
的值,如果后者是值类型的实例。
在默认情况下,PowerShell使用按(可变)值传递;也就是说,传递变量的内容,而不是引用变量本身。
[ref]
-typed参数(类似于ref
C#中的参数)。但是,请注意,在PowerShell中很少需要使用此技术。这是否内容是一份什么样的调用方看到或以相同的对象引用依赖于数据类型的内容:
如果内容碰巧是.NET引用类型的实例(按原样),[pscustomobject]
则该内容是对象引用,因此被调用者可以通过看到与调用者相同的对象来潜在地修改该对象。
System.ICloneable
.Clone()
System.Collections.ArrayList
[ordered]
System.Collections.Specialized.OrderedDictionary
ICloneable
.psobject.Copy()
类型的实例[pscustomobject]
来创建浅表副本。(做不使用任何其他类型的,在那里它将有效地是一个空操作的对象此方法。)类似地,个别的.NET类型可以实现定制克隆方法。相反,如果该内容是.NET值类型的实例(例如[int]
-)或字符串[2],则传递该实例的独立副本。
这种区别是.NET的基础,而不是特定于PowerShell。例如,这也是在C#中传递参数的方式。
要确定给定变量的值是值类型的实例还是引用类型的实例,请使用类似以下内容的方法:
1, (Get-Date), (Get-Item /) | # sample values
foreach {
'{0} is of type {1}; is it a value type? {2}' -f $_,
$_.GetType(),
$_.GetType().IsValueType
}
您会看到类似以下内容:
1 is of type System.Int32; is it a value type? True
4/30/2020 12:37:01 PM is of type System.DateTime; is it a value type? True
/ is of type System.IO.DirectoryInfo; is it a value type? False
如果您查找给定.NET类型的文档,例如System.DateTime
,继承信息将以Object -> ValueType
值类型开头;用C#术语来说,值类型是astruct
或an enum
,而引用类型是a class
。
这里有两个不相关的概念,它们都使用术语(按值)和(按引用)可能会引起混淆:
传递(变量)值与传递(变量)参考参数是一个数据持有者(变量)概念:
引用类型与值类型纯粹是一个数据概念:
[1]浅克隆表示作为引用类型实例的属性值按原样复制(作为引用),这意味着克隆的属性值再次引用与原始对象相同的对象。深层克隆意味着将递归地克隆此类属性值。深克隆很昂贵,而且并非总是可能的。
[2]字符串([string]
)从技术上讲也是引用类型的实例,但作为例外,它被视为值类型;有关此异常背后的原因,请参见此答案。
[3]另一种思考方式:传递对变量存储其值的位置的引用(指针)。这样,被调用者不仅可以访问变量的值,还可以分配(新)值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句