我有一些用Set-Variable myVar -Value 10 -Option ReadOnly
语法设置的只读变量,但我也需要只读数组。如何制作只读数组?
谢谢
答案 0 :(得分:3)
PetSerAl像以前一样无数次,在对该问题的简短评论中提供了解决方案;他还帮助改善了这个答案:
使用[Array]::AsReadOnly($someArray)
,可在 PSv3 + [1] 中使用
:
# Create a 2-element read-only collection containing strings.
$readOnlyColl = [Array]::AsReadOnly(('one', 'two'))
# Try to modify an element, which now fails:
$readOnlyColl[0] = 'uno'
在 PSv2 中,使用强制转换为[System.Collections.ObjectModel.ReadOnlyCollection[<type>]]
,如下所示。
上面产生了以下内容,表明不能修改元素:
Unable to index into an object of type System.Collections.ObjectModel.ReadOnlyCollection`1[System.String].
请注意,该错误消息在某种程度上具有误导性,因为它仅是不允许通过索引进行 write 访问, read 访问(例如$readOnlyColl[0]
)效果很好。
虽然 $readOnlyColl
并不是严格意义上的数组,但它的行为就像一个
出于所有实际目的。
从技术上讲,$readOnlyColl
是泛型类型System.Collections.ObjectModel.ReadOnlyCollection`1
的实例,它使用从输入数组的元素推断出的元素类型。 [2]
注意事项:返回集合只是围绕数组的包装器 ,并且,根据您应用的特定输入数组和类型,其后的修改输入数组的元素可以反映在包装器集合中。 [3]
如果要显式控制元素的数据类型 ,请使用 cast 。
例如,根据[string]
个值创建一个[int]
类型的集合:
# Cast to an array of the desired type first.
[Array]::AsReadOnly([string[]] (1, 2, 3)
# Alternatively, cast to the target collection type directly.
# Always use this in PSv2, where [Array]::AsReadOnly() cannot be called.
[System.Collections.ObjectModel.ReadOnlyCollection[string]] (1, 2, 3)
将[object[]]
/ [object]
用于[object]
类型的元素,与常规PowerShell数组一样,但是请注意,如果输入数组确实已经是[object[]]
数组,则所得的集合将是围绕数组的包装器-参见脚注[2]。
仅说明为什么Set-Variable myVar -Option ReadOnly
不足以创建只读的 array :它使 variable 只读,表示您不能为 it 分配其他值;相比之下,不会阻止修改恰好存储在变量中的数据的属性(例如数组的元素)。
[1]该方法自建立PSv2的.NET v2开始可用;但是,只有PSv3引入了直接调用 generic 方法的功能,因此需要PSv3 +。但是,在PSv2中,您可以直接转换为[System.Collections.ObjectModel.ReadOnlyCollection[<type>]]
。
[2]也就是说,即使PowerShell默认创建[object[]]
数组,如果实际元素碰巧都是同一类型,PowerShell会选择该特定类型而不是[object]
;在当前情况下,由于输入数组的两个元素都是 strings ,因此在幕后创建了一个新的[string[]
类型的数组,其结果是只读集合 wraps < / em>作为[System.Collections.ObjectModel.ReadOnlyCollection[string]]
类型。
[3]因为该集合只是输入数组周围的包装器,所以任何有权访问该输入数组的人都可以修改其元素,而包装器集合将反映该更改。 br />
但是,在 PowerShell 中,如果 PowerShell恰巧在其通过的场景后面创建了一个 new 数组,则通常会避开此潜在问题到[Array]::AsReadOnly()
。假设您没有在[object[]]
调用中将这样的数组显式转换为[object[]]
,则会为PS数组([Array]::AsReadOnly()
)创建一个新数组,其元素都恰好具有相同的类型。对于特定类型的输入数组(例如[int[]]
),仅当您强制转换为不同类型(例如[string[]]
)时,才会创建新数组;创建 no 新数组时包装器问题的演示:
$arr = [int[]] (1..3); $coll = [Array]::AsReadOnly($arr); $arr[1] = 42; $coll[1]
-$coll[1]
现在反映了42
,即通过基础数组$a
分配的 changed 值。