5

I have a c# method I am loading from a dll with optional string arguments that default to null. For example

public void foo(string path, string new_name = null, bool save_now = true)
{
    if(name == null)
        new_name = Path.GetFileNameWithoutExtension(path);
    ...
    if(save_now)
       Save();
}

I want to call this from within a powershell script and not supply a value for new_name but one for save_now. As per this seemingly very similar question I have tried

$default = [type]::Missing
$obj.foo($path, $default, $false)

but this results in new_name being set as "System.Reflection.Missing" within the function.

Additionally I tried

$obj.foo($path, $null, $false)

but this results in new_name being set to the empty string, still not null. I could set the default to the empty string, but I was wondering if there was any good way to actually have the default value be used.

Community
  • 1
  • 1
irh
  • 358
  • 2
  • 10
  • 1
    I'm pretty sure you could build something to do this with reflection. `GetMethod` returns a `MethodInfo`, which has a `GetProperty` method. It returns a `ParameterInfo` which has `DefaultValue, HasDefaultValue, and IsOptional` properties. So you could develop a PS function, say "InvokeWithNamedParameters" that emulates what VB supports. – Χpẘ Mar 02 '16 at 03:43
  • Interesting idea. For me unfortunately the window to try this solution has passed, but maybe someone else with the same question will find this a viable technique. – irh Mar 02 '16 at 23:45

2 Answers2

5

No can do in PowerShell. It doesn't support C#/VB optional parameters. It is the duty of the language calling the method to provide the default values when the programmer doesn't and PowerShell just doesn't do that.

Keith Hill
  • 194,368
  • 42
  • 353
  • 369
4

You can simply omit the optional parameters in the call. I modified your example to run it in PS. For example:

$c = @"
    public static class Bar {
        public static void foo(string path, string new_name = null, bool save_now = true)
        {
            System.Console.WriteLine(path);
            System.Console.WriteLine(new_name);
            System.Console.WriteLine(save_now);
        }
    }
"@

add-type -TypeDefinition $c

[Bar]::Foo("test",[System.Management.Automation.Language.NullString]::Value,$false)

This generates the following

test
False

Test was passed explicitly, null is null and had no output, and the save_now evaluated to the default of True.

StephenP
  • 3,895
  • 18
  • 18
  • Thanks for the reply, but this still misses my question. I *do* want to supply a value for the last optional parameter, but not the middle one. Also, my C# is being imported from a dll, though I don't know if that changes things. – irh Jul 02 '14 at 00:03
  • 1
    I see what you mean now. You can use [System.Management.Automation.Language.NullString]::Value in v3 which should do what you want. Powershell likes to cast $null to be an empty string. References http://msdn.microsoft.com/en-us/library/system.management.automation.language.nullstring(v=vs.85).aspx and https://connect.microsoft.com/PowerShell/feedback/details/307821/it-isnt-possible-to-pass-null-as-null-into-a-net-method-that-has-a-parameter-of-type-string – StephenP Jul 02 '14 at 00:09