12

I have this code:

    $csvUserInfo = @([IO.File]::ReadAllLines($script:EmailListCsvFile))
    $x = $csvUserInfo.ToList()

When it runs, I get this error:

Method invocation failed because [System.String] does not contain a method named 'ToList'.

Why is $csvUserInfo of type String?

Doesn't [IO.File]::ReadAllLines return a string[] ?

I've tried with/without the @ as well, it makes no difference.

1
  • 1
    Anytime you want to know what a type is, use $variable.GetType().FullName. This will avoid automatically unrolling of collections. To see the members available arrays or collections do this Get-Member -Input $variableName and not $variableName | Get-Member. The latter will automatically unroll the collection and you will get member info on the items contained in the collection. Commented Feb 13, 2014 at 2:49

2 Answers 2

18

No, you are right. As shown here, [IO.File]::ReadAllLines does return a String[] object. The confusing error that you are seeing is explained in @mjolinor's answer (I won't repeat it here).

Instead, I will tell you how to fix the problem. To convert a String[] object into a List<String> object in PowerShell, you need to explicitly cast it to such:

PS > [string[]]$array = "A","B","C"
PS > $array.Gettype()

IsPublic IsSerial Name                                     BaseType                                      
-------- -------- ----                                     --------                                      
True     True     String[]                                 System.Array                                  


PS > 
PS > [Collections.Generic.List[String]]$lst = $array
PS > $lst.GetType()

IsPublic IsSerial Name                                     BaseType                                      
-------- -------- ----                                     --------                                      
True     True     List`1                                   System.Object                                 

PS >

In your specific case, the code would be:

$csvUserInfo = [IO.File]::ReadAllLines($script:EmailListCsvFile)
[Collections.Generic.List[String]]$x = $csvUserInfo
Sign up to request clarification or add additional context in comments.

Comments

3

It does return [string[]], but that type doesn't have a tolist() method. I believe what you're seeing is the automatic member enumeration that was introduced in V3. V2 throws the same error, but for [System.String[]].

It looked for that method on the array, and didn't find it so it tried a member enumeration, to see if it was a method of the array members. It didn't find it there either, and that's where it gave up so you got the error on the array member object.

8 Comments

I remember when the first CTPs of V3 came out with the member enumeration feature. I really, really liked it especially for dealing with XML. However, in retrospect, I wish this feature would have required a different syntax so you knew, when reading script, that this feature was being using. Not sure what that syntax would look like - maybe $xml.doc..book.title??
Why does the equivalent C# code work?: string[] csvUserInfo = File.ReadAllLines(EmailListCsvFile); List<string> x = csvUserInfo.ToList();
C# != PowerShell. They are close in some manner but PowerShell is designed for pipeline.
I know they're different, but if they are both based on .NET, why wouldn't it work?
@Backwards_Dave: ToList is an extension method, which the C# compiler will resolve based on the declared type of the object and the using declarations in the file (assuming no local method is found). The PowerShell language and the .NET runtime have no concept of using declarations or extension methods.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.