Discussion:
Passing array to .Net command: discrete parameters
(too old to reply)
Mike Bridge bridgecanada _ com>
2006-10-06 20:08:02 UTC
Permalink
Hi-

I was trying to instantiate some .Net objects from PowerShell, and I am
confused about why this happens when I pass an array to the constructor:

PS [Scripts] > $bytes=@([System.Text.Encoding]::UTF8.GetBytes("Hello
There"))
PS [Scripts] > new-object System.IO.MemoryStream($bytes)
New-Object : Cannot find an overload for ".ctor" and the argument count: "11".
At line:1 char:11
+ new-object <<<< System.IO.MemoryStream($bytes)

I see that this will work if I do this:

PS [Scripts] > new-object System.IO.MemoryStream(,$bytes)

However, I don't understand why my byte array of length 11 is getting passed
as 11 parameters instead of as an array. Does anyone know why this happens?
Is this the correct way to do this?

Thanks!

-Mike
Lee Holmes [MSFT]
2006-10-11 15:43:00 UTC
Permalink
The constructor of a class takes an array of arguments. You normally
specify the array by hand:

$foo = new-object "Int32[,]" 5,6

But you can also pass it in as a regular array, as you've found. If one of
those arguments needs to be an array itself, you need to wrap it in an array
(as you've also found.)

--
Lee Holmes [MSFT]
Windows PowerShell Development
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.
Post by Mike Bridge bridgecanada _ com>
Hi-
I was trying to instantiate some .Net objects from PowerShell, and I am
There"))
PS [Scripts] > new-object System.IO.MemoryStream($bytes)
New-Object : Cannot find an overload for ".ctor" and the argument count: "11".
At line:1 char:11
+ new-object <<<< System.IO.MemoryStream($bytes)
PS [Scripts] > new-object System.IO.MemoryStream(,$bytes)
However, I don't understand why my byte array of length 11 is getting passed
as 11 parameters instead of as an array. Does anyone know why this happens?
Is this the correct way to do this?
Thanks!
-Mike
Mike Bridge
2006-10-11 16:31:40 UTC
Permalink
Hi-

But what's the justification behind the fact that I need to tell the
shell that my array is an array? Can't it tell what it is?

Thanks,

-Mike



On Wed, 11 Oct 2006 08:43:00 -0700, "Lee Holmes [MSFT]"
Post by Lee Holmes [MSFT]
The constructor of a class takes an array of arguments. You normally
$foo = new-object "Int32[,]" 5,6
But you can also pass it in as a regular array, as you've found. If one of
those arguments needs to be an array itself, you need to wrap it in an array
(as you've also found.)
Lee Holmes [MSFT]
2006-10-11 17:02:46 UTC
Permalink
Sorry, I should have finished the example.

Since the constructor takes an array of arguments, that means you can do
this:

$arguments = 5,6
$foo = new-object "Int32[,]" $arguments

We treat that as an array of arguments, rather than a single argument that
should be an array.

--
Lee Holmes [MSFT]
Windows PowerShell Development
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.
Post by Mike Bridge
Hi-
But what's the justification behind the fact that I need to tell the
shell that my array is an array? Can't it tell what it is?
Thanks,
-Mike
On Wed, 11 Oct 2006 08:43:00 -0700, "Lee Holmes [MSFT]"
Post by Lee Holmes [MSFT]
The constructor of a class takes an array of arguments. You normally
$foo = new-object "Int32[,]" 5,6
But you can also pass it in as a regular array, as you've found. If one of
those arguments needs to be an array itself, you need to wrap it in an array
(as you've also found.)
Bruce Payette [MSFT]
2006-10-11 17:23:13 UTC
Permalink
The shell knows it's an array. The problem is primarily with the New-Object
cmdlet. The issue is that New-Object takes 2 arguments - the type to
construct and an array of arguments to pass to that constructor. It's the
fact that it always takes an array of constructor arguments that's causing
the problem. If you pass a scalar to a cmdlet that requires an array, we'll
wrap it up in an array. If you pass it an array, then it stays as an array.
If your intention was to pass a single argument that is itself an array,
then you have to explicitly wrap it up in a container array yourself. The
upside of this is that you can incrementally build up the constructor
arguments. So you can do

$x = new-object foo 1,2,3

or

$a = 1,2
$a += 3
$x = new-object foo $a

An arguably better signature for new-object would be for it to take a
variable number of arguments. Then you could write

new-object foo 1 2 3 # constructer with three scalar args
new-object foo 1,2,3 # constructor with 1arg that is an array
new-object foo 1,2,3 2 # constructor with 3 args, one array and one scalar

The downside of this signature is that you can't do the other trick (which
is, admittedly, not a very common pattern.)

Longer term, I expect that we'll actually add a "new" keyword to the
language and all of this discussion will become moot...

-bruce
--
Bruce Payette [MSFT]
Windows PowerShell Technical Lead
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.
Post by Mike Bridge
Hi-
But what's the justification behind the fact that I need to tell the
shell that my array is an array? Can't it tell what it is?
Thanks,
-Mike
On Wed, 11 Oct 2006 08:43:00 -0700, "Lee Holmes [MSFT]"
Post by Lee Holmes [MSFT]
The constructor of a class takes an array of arguments. You normally
$foo = new-object "Int32[,]" 5,6
But you can also pass it in as a regular array, as you've found. If one of
those arguments needs to be an array itself, you need to wrap it in an array
(as you've also found.)
Loading...