Why does calling a Powershell script block with .Invoke () return a collection?

It seems that calling the Powershell script block (by calling the .Invoke() method) always creates a collection. In particular, a set of types

System.Collections.ObjectModel.Collection`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]

Even calling an empty block script ( {}.Invoke() ) returns a collection. Calling the same script block using the call operator ( & ) gives the expected return (both a scalar and [object[]] ).

This is convenient if you need a collection instead of an array, but it seems to be the opposite.

Does anyone know why he behaves this way?

Edit:

I knew that there are two different calls, .Invoke() and .InvokeReturnAsIs() from reading the language specification. This is the first time I noticed.

I just do not understand the reasons underlying the agreement on the names and methods of mechanics. If you look at the documentation, I would think that this is the default invocation method - this is not what is used when the script script is called in Powershell. It looks like .InvokeReturnAsIs() just returns a stream of objects, and then Powershell wraps it in an array of objects if there is more than one object, like a scalar if there is only one object, or creates a null object if it isn't there, as if there implicit pipeline. Using .Invoke() returns the collection, always, and Powershell leaves it as a collection.

+4
source share
3 answers

It looks like the difference between these two methods:

Challenge . Invokes a script block with the specified arguments, returning the results as PSObjects.

InvokeReturnAsIs . Runs a script block with the specified arguments. This method returns raw (expanded) objects of the result so that it can be more efficient.

http://msdn.microsoft.com/en-us/library/system.management.automation.scriptblock_methods(v=vs.85).aspx

Invoke

 $code = {"a"} $code.Invoke().Gettype().FullName 

Output:

 System.Collections.ObjectModel.Collection`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]] 

InvokeReturnAsIs

 $code.InvokeReturnAsIs().GetType().FullName 

Output:

 System.String 
+9
source

I assume that the team wanted to be compatible with the PowerShell.Invoke() API , which returns a Collection<PSObject> . This C # signature makes it easier for customers to consume 0, 1, or N returned values ​​and there is no need to worry about checking for zero and whether the returned object was wrapped or not.

From the .NET Design Guidelines :

DO NOT return null values ​​from collection properties or from methods returning collections. Return an empty collection or an empty array instead.

Then you can say why not just return an object . Then I would have to be against null or not, and then I would need to check if ICollection was implemented to determine if I have a scalar or collection. From the perspective of C # dev, this is an eruption (pardon the rhyme). :-)

+5
source

Because it is what it is intended, and there is an alternative!

Invoke - calls a script block with the specified arguments, returning the results as a (set) of PSObjects.

InvokeReturnAsIs - Runs a script block with the specified arguments. This method returns raw (expanded) objects of the result so that it can be more efficient.

Also, {}.invoke() returns null, so I don’t know where you got the impressions, which even return the collection.

http://msdn.microsoft.com/en-us/library/system.management.automation.scriptblock.invokereturnasis(v=vs.85).aspx

+1
source

Source: https://habr.com/ru/post/1393293/


All Articles