1

I have created a List<string> in PowerShell and want to sort this list using a script block with the code below:

$AssemblyNames = New-Object "System.Collections.Generic.List[string]"
$AssemblyNames.Add("PersonService.BizTalk.dll")
$AssemblyNames.Add("PersonService.BizTalk.Schemas.dll")
$SortedAssemblyNames = $AssemblyNames | Sort-Object { if ($_.ToLower().Contains("schema")) { 0 } else { 1 } }
$SortedAssemblyNames

which outputs:

PersonService.BizTalk.Schemas.dll
PersonService.BizTalk.dll

All fine, but I want to remove some elements later in processing these elements using:

$SortedAssemblyNames.Remove($SortedAssemblyNames.Item($i))

This produces the error

Exception calling "Remove" with "1" argument(s): "Collection was of a fixed size.

So I checked the type of the $SortedAssemblyNames variable and I get System.Object[]. And this is strange as the Sort-Object documentation states:

Outputs

The output type is the type of the objects that the cmdlet emits.

And in my opinion, this should be System.String[]. Am I wrong or is there a way to specify the output type of the Sort-Object cmdlet?

My current workaround is to loop through this collection and add it to a new List<string> but I think there should be a better solution as I need to modify the collection later and arrays are a pain.

0

2 Answers 2

1

It is how pipeline works:

  • Sort-Object does not see your list. Your list enumerated by PowerShell and each individual item passed to Sort-Object.
  • Sort-Object does not return array. Sort-Object write each individual item to the pipeline. PowerShell sees, that pipeline return more than one item and pack them into array.
  • When PowerShell need to pack multiple pipeline results into array, it always create System.Object[] array. It does not try to find common most derived element type of array.
Sign up to request clarification or add additional context in comments.

3 Comments

I agree it does not see the list. That's why I expected the output to be of type System.String[] as the type of each individual object is System.String. But maybe this is a documentation issue (or I don't understand it correctly).
@Scoregraphic Do you expect that PowerShell will check type of each returned item and create array with common most derived type as element type? And, BTW, returned items likely would be wrapped in PSObject, so it can not be System.String[].
Not each item, but the first one and uses this type information to create the output type. As I'm writing this, I see that this would generate issues if you input objects out of a List<object>. Nevertheless is the documentation missleading.
1

In addition to what @PetSerAl said, this should work;

$AssemblyNames | Sort-Object { if ($_.ToLower().Contains("schema")) { 0 } else { 1 } } -OutVariable SortedAssemblyNames
$SortedAssemblyNames.Remove($SortedAssemblyNames.Item($i))

If it's implemented in a different way than you show here you might have to use -OutVariable +SortedAssemblyNames in order to not overwrite values (the + infront of the variable name).

Comments

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.