5

In PowerShell one can define C# code and execute it. Passing in $null into the following simplest function shows that not null gets passed into the function

Add-Type -TypeDefinition @"
public static class foo
{
public static void fooo(string a)
{
    if(a!=null)
    {
        System.Console.WriteLine("Not Null. Is '" + a + "'");
    }
}
}
"@ -Language CSharp

Calling it as follows leads to the output Not Null. Is ''. This shows that $null was not null in C#. Methods like 'IsNullOrEmpty' or 'IsNullOrWhiteSpace' return true, so PowerShell must have implicitly converted the $null into a string.

[foo]::fooo($Null)

Any ideas why this is happening and if there is a better fix apart from rather calling String.IsNullOrEnpty in C#? NB: This happens irrespective of the C# language specified 'Add_Type'. I'm using PowerShell V5.

bergmeister
  • 949
  • 2
  • 10
  • 16
  • `[foo]::fooo([String] $null)`, `[foo]::fooo($null -as [String])`, and `$s = $null; [foo]::fooo($s)` all yield the same result. If the type of parameter `a` is changed from `string` to `object` then `fooo` no longer prints any output. That suggests PowerShell is trying to be "smart" in its handling of `string` parameters. – Lance U. Matthews Aug 15 '16 at 16:39
  • The same behavior can be observed with the new class support in PowerShell 5.0 (`class foo { static fooo([String] $a) { if ($a -ne $null) { [Console]::WriteLine("Not Null. Is '" + $a + "'"); } } }; [foo]::fooo($null);`) as well as plain old PowerShell functions (`function fooo([String] $a) { if ($a -ne $null) { [Console]::WriteLine("Not Null. Is '" + $a + "'"); } }; fooo $null;`), so this must be how PowerShell handles `string` parameters in general. – Lance U. Matthews Aug 15 '16 at 16:51
  • Where are you defining a? – Austin T French Aug 15 '16 at 18:09
  • Possible duplicate of [Possible to pass null from Powershell to a .Net API that expects a string?](http://stackoverflow.com/questions/2002570/possible-to-pass-null-from-powershell-to-a-net-api-that-expects-a-string) – Lance U. Matthews Aug 16 '16 at 18:36
  • Thanks for your investigation. Seems like this is just PowerShell trying to be overly helpful. I knew that PowerShell sometimes casts objects without asking to be 'helpful' but I did not expect it to actually instantiate it an object. I suppose using String.IsNullOrEmpty() in C# code is the best solution to deal with this problem. – bergmeister Aug 17 '16 at 23:30

1 Answers1

6

Evidently the solution is "don't pass $null to a [String] parameter if you want a $null [String]". There is a special [NullString] class that should be used instead.

PS > [foo]::fooo($Null)
Not Null. Is ''
PS > [foo]::fooo([NullString]::Value)
PS >

I can't find any mentions of the need to use [NullString] in the PowerShell documentation, nor does the source code for the NullString class include any comments explaining its purpose.

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
  • 1
    See [documentation `NullString` Class](https://msdn.microsoft.com/en-us/library/system.management.automation.language.nullstring.aspx). This possibility was new in PowerShell 3 (since 2012). – Jeppe Stig Nielsen Oct 17 '16 at 12:21