如何创建只读数组? [英] How to create Readonly array?

查看:54
本文介绍了如何创建只读数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have some read-only variables set with Set-Variable myVar -Value 10 -Option ReadOnly syntax but I need read-only arrays too. How do I make read-only arrays?

谢谢

推荐答案

PetSerAl 对问题的简短评论中的解决方案;他还帮助改善了这个答案:
使用 [Array] :: AsReadOnly($ someArray) ,在 PSv3 + [1] 中可用:

PetSerAl, as countless times before, has provided the solution in a terse comment on the question; he's also helped to improve this answer:
Use [Array]::AsReadOnly($someArray), available in 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>]] ,如下所示.

In PSv2, use a cast to [System.Collections.ObjectModel.ReadOnlyCollection[<type>]], as shown below.

上面产生了以下内容,表明不能修改元素:

The above yields the following, demonstrating that elements cannot be modified:

Unable to index into an object of type System.Collections.ObjectModel.ReadOnlyCollection`1[System.String].

请注意,该错误消息在某种程度上具有误导性,因为它仅是不允许通过索引进行 write 访问, read 访问(例如, $ readOnlyColl[0] )就可以了.

Note that the error message is somewhat misleading, because it is only write access via indexing that isn't allowed, read access (e.g., $readOnlyColl[0]) works just fine.

虽然 $ readOnlyColl 并不是严格意义上的数组,但其行为却像一个出于所有实际目的.
从技术上讲, $ readOnlyColl 是通用类型 System.Collections.ObjectModel.ReadOnlyCollection`1 的实例,它使用从输入数组的元素推断出的 element类型. [2]
注意事项:返回集合只是围绕数组的包装器 ,并且,根据您应用的特定输入数组和演员,以后对输入数组的元素可以反映在包装器集合中. [3]

While $readOnlyColl is not strictly an array, it behaves like one for all practical purposes.
Technically, $readOnlyColl is an instance of generic type System.Collections.ObjectModel.ReadOnlyCollection`1 using an element type inferred from the input array's elements.[2]
Caveat: The return collection is only a wrapper around an array and, depending on the specific input array and casts you apply, later modifications to the input array's elements could be reflected in the wrapper collection.[3]

如果要显式控制元素的数据类型 ,请使用 cast .

例如,根据 [int] 值创建一个 [string] 类型的集合:

E.g., to create a [string]-typed collection from [int] values:

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

Use [object[]] / [object] for [object]-typed elements, as with regular PowerShell arrays, but note that if the input array is indeed already an [object[]] array, the resulting collection will be a wrapper around the array - see footnote [2].

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

Just to spell out why Set-Variable myVar -Option ReadOnly is not enough to create a read-only array: it makes the variable read-only, meaning that you cannot assign a different value to it; by contrast, modifying a property of the data that happens to be stored in the variable - such as an array's element - is not prevented.

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

[1] The method has been available since .NET v2, on which PSv2 is built; however, only PSv3 introduced the ability to call generic methods directly, so PSv3+ is required; however, in PSv2 you can cast to [System.Collections.ObjectModel.ReadOnlyCollection[<type>]] directly.

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

[2] That is, even though PowerShell creates [object[]] arrays by default, if the actual elements happen to be all of the same type, PowerShell chooses that specific type rather than [object]; in the case at hand, because both elements of the input array were strings, a new [string[] typed array was created behind the scenes, which the resulting read-only collection wraps as type [System.Collections.ObjectModel.ReadOnlyCollection[string]].

[3]因为该集合只是输入数组周围的一个包装器,所以有权访问该输入数组的任何人都仍可以修改其元素,而包装器集合将反映该更改.br>但是,在 PowerShell 中,如果 PowerShell碰巧在它随后通过的场景后面创建了一个 new 数组,那么您通常会免受此潜在问题的困扰.到 [Array] :: AsReadOnly().为PS数组( [object []] )创建一个新数组,假设您没有将这样的数组显式转换为 [object []] [Array] :: AsReadOnly()调用中.对于特定类型的输入数组(例如 [int []] ),仅当您强制转换为不同类型(例如 [string []] );创建 no 新数组时包装器问题的演示:
$ arr = [int []](1..3);$ coll = [Array] :: AsReadOnly($ arr);$ arr [1] = 42;$ coll [1] - $ coll [1] 现在反映出 42 ,即通过基础数组 $ a .

[3] Because the collection is only a wrapper around the input array, anyone with access to the input array could still modify its elements and the wrapper collection would reflect that change.
In PowerShell, however, you're often shielded from this potential problem if PowerShell happens to create a new array behind the scenes that it then passes to [Array]::AsReadOnly(). A new array is created for PS arrays ([object[]]) whose elements all happen to have the same type, assuming you don't explicitly cast such an array to [object[]] in the [Array]::AsReadOnly() call. For a specifically typed input array (e.g., [int[]]), a new array is only created if you cast to a different type (e.g., [string[]]); demonstration of the wrapper problem if no new array is created:
$arr = [int[]] (1..3); $coll = [Array]::AsReadOnly($arr); $arr[1] = 42; $coll[1] - $coll[1] now reflects 42, i.e., the changed value that was assigned via the underlying array, $a.

这篇关于如何创建只读数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆