arrays - 如何创建只读数组?

标签 arrays powershell readonly

我有一些用Set-Variable myVar -Value 10 -Option ReadOnly语法设置的只读变量,但我也需要只读数组。如何制作只读数组?

谢谢

最佳答案

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].

请注意,错误消息在某种程度上具有误导性,因为它只是不允许通过索引进行写访问,而读访问(例如$readOnlyColl[0])则可以正常工作。

尽管 $readOnlyColl并非严格意义上的数组,但其行为类似于一个
用于所有实际目的。
从技术上讲,$readOnlyColl是使用从输入数组的元素推断出的元素类型的通用类型System.Collections.ObjectModel.ReadOnlyCollection`1的实例。[2]
警告:返回集合只是数组的包装,并且,根据您应用的特定输入数组和强制类型转换,对输入数组元素的以后修改可能会反射(reflect)在包装器集合中。[3]

如果要显式控制元素的数据类型,请使用强制转换。

例如,根据[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)

与常规PowerShell数组一样,对[object[]]类型的元素使用[object] / [object],但是请注意,如果输入数组确实已经是[object[]]数组,则结果集合将是该数组的包装器-请参见脚注[2]。

只是为了说明,为什么Set-Variable myVar -Option ReadOnly不足以创建只读数组:它使变量为只读,这意味着您不能为其分配其他值。相比之下,不会阻止修改恰好存储在变量中的数据的属性(例如数组的元素)。

[1]该方法自建立PSv2的.NET v2开始可用;但是,只有PSv3引入了直接调用通用方法的功能,因此需要PSv3 +。但是,在PSv2中,您可以直接将其转换为[System.Collections.ObjectModel.ReadOnlyCollection[<type>]]

[2]也就是说,即使PowerShell默认情况下会创建[object[]]数组,但如果实际元素碰巧都是同一类型,那么PowerShell会选择该特定类型,而不是[object];在当前情况下,由于输入数组的两个元素都是字符串,因此在幕后创建了一个新的[string[]类型的数组,生成的只读集合将其包装为[System.Collections.ObjectModel.ReadOnlyCollection[string]]类型。

[3]因为该集合只是输入数组的包装,所以有权访问输入数组的任何人仍可以修改其元素,并且包装集合将反射(reflect)该更改。
但是,在PowerShell中,如果PowerShell恰巧在幕后创建一个新数组,然后将其传递给[Array]::AsReadOnly(),则通常可以避免该潜在问题。假设您没有在[object[]]调用中将此类数组显式转换为[object[]],则会为PS数组([Array]::AsReadOnly())创建一个新数组,其元素都恰好具有相同的类型。对于特定类型的输入数组(例如[int[]]),仅当您强制转换为其他类型(例如[string[]])时才创建新数组;如果未创建新数组,则说明包装器问题:$arr = [int[]] (1..3); $coll = [Array]::AsReadOnly($arr); $arr[1] = 42; $coll[1]-$coll[1]现在反射(reflect)42,即通过基础数组$a分配的更改后的值。

关于arrays - 如何创建只读数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51863182/

相关文章:

powershell - 捕获 PowerShell 工作流程中的错误

asp.net - ASP :TextBox ReadOnly=true or Enabled=false?

c# - 如何在 C# 中填充数组?

java - 我的列表中只有最后添加的数组

java - 通用数组在直接引用时抛出 ClassCastException(在通过辅助方法调用时不会抛出)

c# - 存储:C# 等同于 PowerShell 命令

arrays - Perl:查找哈希的最大值并计算平均值

powershell - 新-AzureRmResourceGroupDeployment : "Deployment ' xxx' could not be found"

c# - 什么是只读集合?

ubuntu - 在 Linux Snappy Ubuntu Core 上更改密码