Data Rows to String to Array issue

[String] $DBNms = @(); makes $DBNms a type-constrained variable, due to type literal [string] being placed to the left of variable $DBNms, whose type is then locked in as a string; that is, as a single string.

You were looking to create a string array, which in PowerShell is represented as [string[]]:

[string[]] $DBNames = @()

PowerShell’s type conversions are automatic (and very flexible), so that [String] $DBNms = @() doesn’t report an error, it quietly converts the empty array (@()) to the empty string (as required by the type constraint):

PS> [string] $DBNames = @(); '' -eq $DBNames
True

A much more efficient way to collect values from multiple iterations in an array is to use the foreach statement as an expression, which case PowerShell collects the outputs automatically for you:

[string[]] $DBNms = foreach ($DBName in $objDBNms){ 

   # Output this expression's value as-is.
   # PowerShell will collect the individual iterations' values for you.
   $DBName.Item(0).ToString().Trim() + "."

}  

The above is not only more concise than your original approach, it is more importantly more efficient:

  • In reality you cannot directly add (append to) an array, because it is an immutable data structure.

  • What PowerShell has to do whenever you use += with an array is to allocate a new array behind the scenes, with the original elements copied over and the new element(s) appended; the new array is then automatically assigned back to the variable.


Note: The alternative and next best solution to using the whole loop as an expression is to use an efficiently extensible list type, notably [System.Collections.Generic.List[object]](System.Collections.Generic.List`1):

# Create the list.
# The 'System.' namespace prefix is optional.
[Collections.Generic.List[string]] $DBNms = @()

foreach ($DBName in $objDBNms) { 

   # Add to the list, using its .Add() method.
   # Note: Do NOT try to add with +=
   $DBNms.Add($DBName.Item(0).ToString().Trim() + ".")

}  

You’ll need this approach if your loop does more than outputting a single value per iteration, such as needing to append to multiple collections.

Note: It used to be common to use System.Collections.ArrayList instances instead; however:

  • Use of this type is no longer recommended (see the warning in the linked help topic); use [System.Collections.Generic.List[object]] instead, which additionally allows you to strongly type the collection (replace [object] with the type of interest, such as [string] in the code above).

  • It has the drawback of its .Add() method having a return value, which you need to silence explicitly (e.g., $null = $lst.Add(...)), so that it doesn’t accidentally pollute your code’s output stream (produce unexpected extra output).

Leave a Comment