18

I just realized this and I've learned it the hard way, so I want to share. Consider you have the following list of strings:

>$list = New-Object -TypeName System.Collections.Generic.List[string]
>$list.Add("x")
>$list.Add("yy")
>$list.Add("zzz")
>$list
x
yy
zzz

Now if you want to get the number of items in the list, you would access the .Count property, and it gives you "3" as expected.

>$list.Count
3

However, sometimes you would make mistake by accessing .Length instead of .Count. In other languages, like Python or C#, you would get an error saying this property is not available. But in PowerShell, it turns out that, if it's not found on that object, it iterates through the contained objects and access the property on them. So you end up having a list of Lengthes! Surprise!!

>$list.Length
1
2
3

You can even invoke methods!

>$list.ToUpper()
X
YY
ZZZ

Note that, as I've tried, this "feature" also works for System.Collections.ArrayList. But it does not work for PowerShell's builtin array type.

What is this "feature" called? And why is it designed such way? It's very surprising and error-prone.

9
  • 6
    It has been called many things. Member enumeration is the latest IIRC. See blogs.msdn.com/b/powershell/archive/2012/06/14/… Commented Jun 5, 2013 at 1:39
  • I don't like this new "feature" (introduced in PSv3) -- it makes your script backwards incompatible with PSv2... :( I really don't think the slightly reduced number of characters justifies breaking backwards compatibility. Commented Jun 5, 2013 at 2:27
  • Andy, I'am getting old, so I somewhere share your opinion, but if some new scripts won't run in PowerShell V2.0, Whatever happens old scripts wich were really working in PowerShell V2.0 will work in PowerShell V3.0. As usual in computer equipment you need to stick to the older technologie, this should not stop technologie to progress. Commented Jun 5, 2013 at 3:22
  • @JPBlanc, I just don't think breaking backwards compatibility was really worth it in this case. This actually happened to me the other day -- developed my script in the PSv3 ISE (awesome) to deploy to a system with PSv2 and ended up having to figure out why there was no member named "..." on my object. IIRC intellisense just gave it to me so I went with it. Commented Jun 5, 2013 at 3:30
  • 2
    @AndyArismendi This wouldn't be the only breaking change in V3 (foreach handling of $null, RootModule in psd1, early pipeline termination, DLR, etc). You can always start up PowerShell v2 that comes with V3 to test your scripts under v2. What was more surprising to me was that we didn't get a .ps3 file extension out of this. FWIW, breaking changes aside, I love this new feature. Walking XML (and nested collections in general) is a whole lot easier IMO. Commented Jun 5, 2013 at 5:39

1 Answer 1

6

Keith Hill mentioned in the comment that this is a new feature called Member Enumeration in V3.

Refer to "New V3 Language Features" on devblogs.microsoft.com.

Sign up to request clarification or add additional context in comments.

1 Comment

To follow-up on @SteveKaye 's comment, I'll at least add the "why" from the excellent link, above. "We added this feature to make it easier to deal with commands that return one or many objects. Experienced PowerShell scripters knew they needed to use @() to handle that situation correctly, but we really thought that was less than perfect... We are not aware of any scripts where this change broke a script, but did not expose an underlying problem in the script." Interesting feature.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.