问题
It seems that there is a bug in the O-O support in PowerShell.
When instantiating an object of a class with a constructor that accepts a List< T > and this is the only parameter, PowerShell cannot find a proper constructor.
Code sample:
class MyClass
{
MyClass(
#[int]$i,
[System.Collections.Generic.List[string]] $theparams)
{
}
}
$parameters = New-Object System.Collections.Generic.List[string];
$foo = New-Object MyClass -ArgumentList @(
#1,
$parameters)
Constructor not found. Cannot find an appropriate constructor for type MyClass.
Uncommenting the [int]
parameter makes it work fine.
Workaround: since Powershell doesn't handle visibility of the members, if the parameter is used to assign a class member then you can directly assign it outside the constructor.
回答1:
To avoid the pitfall discussed here, consider using the class' static ::new()
method (PSv5+), as demonstrated in TheIncorrigible1's helpful answer.
Note: The following applies not just to New-Object
, but to all cmdlets that accept an array of arguments via a single parameter (typically named -ArgumentList
/ alias -Args
), notably also Invoke-Command
and Start-Job
.
To find all commands that have an -ArgumentList
parameter, run Get-Help * -Parameter ArgumentList
To pass a collection as a whole as the only argument to New-Object
's -ArgumentList
parameter, you must wrap it in an aux. array using ,
, the array-construction operator[1]:
New-Object MyClass -ArgumentList (, $parameters)
Without the wrapper, the elements of collection $parameters
would be interpreted as individual constructor arguments.
However, if there is at least one other explicitly enumerated argument, the wrapping is no longer needed:
# With `[int] $i` as the 1st constructor argument defined:
New-Object MyClass -ArgumentList 1, $parameters
The reason is that 1, $parameters
constructs an array in a manner that implicitly passes $parameters
as a single argument: $parameters
as a whole becomes the array's 2nd argument.
[1] Note that @($parameters)
would not work, because @(...)
, the array-subexpression operator, is a no-op (loosely speaking) if the expression already is an array.
I say loosely speaking, because @(...)
actually rebuilds the input collection as a (new) [object[]]
array - which has performance implications and can result in a different collection type.
回答2:
I suggest you use the constructor syntax since you're on PSv5 anyways. This worked in my testing and there may be something funky going on with New-Object
:
class MyClass
{
MyClass([System.Collections.Generic.List[string]] $Params) { }
}
[MyClass]::new([System.Collections.Generic.List[string]]::new())
来源:https://stackoverflow.com/questions/49307620/powershell-cannot-find-proper-ctor-when-the-ctor-has-only-one-argument-of-typ