PowerShell: Cannot find proper .ctor when the .ctor has only one argument of type List<T> [duplicate]

六月ゝ 毕业季﹏ 提交于 2021-02-19 07:16:47

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!