问题
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