[Powershell] Powershell中的动态数组

This artical will also be published in English http://www.cnblogs.com/LarryAtCNBlog/p/4252464.html

又或者说是C#? 因为powershell本源就是C#。当然,标题是个伪命题,根据如下MSDN页所述,对于一个array对象来说,IsFixedSize属性一直就是true的。

https://msdn.microsoft.com/en-us/library/system.array.isfixedsize(v=vs.110).aspx

换句说话就是array里的成员对象数量是固定的,在powershell里用如下的方法添加对象后实际上是复制了一份新数组,而打破了原有的地址指向。

$t = 1..2
$r = $t
$r[1] = 9
$t
# $t的输出为1, 9,因为$r和$t实际上指向的同一个数据,类似于指针
######
$r += 10
$t
# $t的输出依然会是1, 9,因为后台C#所做的实际上是复制了一份原有数组加入新的值后赋给了$r

这种数组添加方式真心简单到爆,但是对资源的开销大了不少,不过脚本嘛就要有脚本的样子,简单易用才是正道。

但是如上面代码里所说,这种方法虽然简单但是却打破了原本$r和$t指向同一个数组的事实,原本我只需要改动$t或$r任一个里的元素值,另一个也会跟着变化,但是这种添加元素的方法却clone了一个新数组使得$t和$r指向了不同的指针。

有的时候真得非常需要两个变量指向同一个数组指针一起更新数据,比如线程间的通信,但是元素数量的改动又是必须的,理所当然,会想到array本身可能有方法做这这个吧?事实是有,也同时没有。看如下数组和对象的静态方法,

Remove         Method                void IList.Remove(System.Object value)
RemoveAt       Method                void IList.RemoveAt(int index)
# 当使用remove和removeAt的时候会报错说这个collection是fixed size的
Clear             Method     static void Clear(array array, int index, int length)
# 当使用[array]::clear($t, 1, 1)的时候的确可以清空最后一个元素的值,但是数组的成员数量依然不会改变

我想要的只是多个变量指向同一个数组且我能改变数组的成员数量并不影响前一条。

我之前一直关注在array对象上,想着会不会有什么wonderful方法能直接实现我所想的,事实证明是错误的。于是我转向了IsFixedSize这个属性,想找一找有没有其它对象足够像array但是这个IsFixedSize属性却可以是false的,于是找到了ArrayList

https://msdn.microsoft.com/en-us/library/system.collections.arraylist(v=vs.110).aspx

$t = New-Object System.Collections.ArrayList
$t.IsFixedSize
# 输出为false

很好,第一步实现了,它是动态的,调用元素的方法也和普通array一样。它填充元素的方法类似于hash table,感觉十分友好。

Add            Method                int Add(System.Object value), int IList.Add(System.Object v...
AddRange       Method                void AddRange(System.Collections.ICollection c)
Remove         Method                void Remove(System.Object obj), void IList.Remove(System.Ob...
RemoveAt       Method                void RemoveAt(int index), void IList.RemoveAt(int index)
RemoveRange    Method                void RemoveRange(int index, int count)
TrimToSize     Method                void TrimToSize()
Capacity       Property              int Capacity {get;set;}
Count          Property              int Count {get;}

Add是增加单个元素在数组的最后,AddRange则是把另一个Collection的对象复制到它的最后面,这就解决了元素增加的问题。

Remove* 的3个方法则是在数组中删掉相应的元素,这解决了元素减少的问题。

Count和Capacity属性会随着元素增加而增长,但Capacity不会随着元素减少而自减,Count属性则会,这解决了元素Get and Set的问题。

TrimToSize也就是Align count和Capacity属性,把该数组的capacity置于和count一样。

至此,我之前想要的"多个变量指向同一个数组且我能改变数组的成员数量并不影响前一条"已经实现~~

那么这种对象实现起来这么容易,开销呢?

无论从内存或者说是cpu来说开销自然也是大不少的,最简单的测试就是开俩powershell分别用这两种办法建一个大数组如1..1000000,然后就能从内存中看出明显的占用区别,至于CPU时间太短直观的感觉不容易发现罢了。简单易用的后台是Powershell或者说C#在帮我们处理而已,当然,之前提及过,脚本就要有脚本的样子,自动化才是关注的重点~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章