該Length屬性在我測驗的所有陣列上都按預期作業,除了一種奇怪的情況:
PS> @(@()).Length
0
但是,通常不會省略空陣列:
PS> @(@(), @()).Length
2
PS> @(@(), @(), @()).Length
3
這是怎么回事?
uj5u.com熱心網友回復:
@(...),陣列子運算式運算子不是陣列構造函式,它是陣列“擔保人”(見下一節),嵌套@(...)操作毫無意義。@(@())實際上與 相同@(),即型別為空的陣列[object[]]。
要無條件地構造陣列,請使用
,陣列建構式 operator。要為單個物件構造一個陣列包裝器,請使用 的一元形式
,,正如Abraham Zinala所建議的:# Create a single-element array whose only element is an empty array. # Note: The outer enclosure in (...) is only needed in order to # access the array's .Count property. (, @()).Count # -> 1
請注意,我使用.Count的不是.Length上面的,它更符合 PowerShell 的習慣;.Count適用于不同的集合型別。即使System.Array不直接實作.Count,它也是通過ICollection介面實作的,并且 PowerShell 允許訪問介面成員而無需強制轉換。
背景資料:
@(...)的主要目的是確保從 - 總是基于管道-命令(例如,@(Get-ChildItem *.txt))收集的輸出物件始終作為陣列(總是型別[object[]])收集 - 即使...只產生一個輸出物件。如果需要獲取一個陣列,
@(...)則必須使用 of,因為收集碰巧只包含一個物件的輸出默認情況下會按原樣收集,即不包裝在陣列中(這也適用于您使用$(...)子運算式運算子時)。請注意,PowerShell 命令(通常)不輸出集合;相反,它們將一個(通常是開放式的)物件一個一個地流式傳輸到管道;因此,捕獲命令輸出需要收集流式傳輸的物件 - 有關更多資訊,請參閱此答案。
@(...)的次要目的是便于定義陣列字面量,例如@('foo', 'bar')筆記:
@(...)出于此目的使用并非最初的設計,但這種使用變得如此普遍,以至于在 PowerShell 版本 5 中實作了優化,例如,1, 2這足以宣告一個 2 元素陣列 - 也可以表示為@(1, 2)沒有不必要的處理開銷。從好的方面來說,在宣告空陣列( ) 或單元素陣列 (例如) 時
@(...)在視覺上是獨特的和方便的- 如果沒有,這些將不得不分別表示為和。@()@(42)@(...)[object[]]:new(), 42但是,這種使用會
@(...)引起誤解,認為它充當無條件陣列建構式,事實并非如此。簡而言之:圍繞一個操作包裝額外的操作不會創建嵌套陣列,它是一個昂貴的無操作@(...)@(...);例如:@(42) # Single-element array @(@(42)) # !! SAME - the outer @(...) has no effect.
當
@(...)應用于(非陣列文字)運算式時,此運算式的計算結果將被發送到管道,如果它認為它是可列舉的,則會導致 PowerShell列舉它;[1]也就是說,如果運算式結果是一個集合,它的元素會被一個接一個地發送到管道,類似于命令的流輸出,然后再被收集到一個[object[]]陣列中。# @(...) causes the [int[]]-typed array to be *enumerated*, # and its elements are then *collected again*, in an [object[]] array. $intArray = [int[]] (1, 2) @($intArray).GetType().FullName # -> !! 'System.Object[]'為了防止這種列舉和重新收集:
按原樣使用運算式,如有必要,將其括在
(...)為了再次確保回傳一個陣列,一個有效的替代方法
@(...)是使用[array]強制轉換;唯一需要注意的是,如果運算式的計算結果為$null,則結果也將是$null($null -eq [array] $null):# With an array as input, an [array] cast preserves it as-is. $intArray = [int[]] (1, 2) ([array] $intArray).GetType().FullName # -> 'System.Int32[]' # With a scalar as input, a single-element [object[]] array is created. ([array] 42).GetType().FullName # -> 'System.Object[]'
[1] 有關PowerShell 認為在管道中可列舉的 .NET 型別的概述,請參閱此答案的底部部分。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/495218.html
