【发布时间】:2017-08-16 17:56:07
【问题描述】:
考虑以下代码:
function f {
param (
[AllowNull()]
[string]
$x
)
return $x
}
$r = f -x $null
$null 在达到return 时转换为[string]::Empty。 $null 与 [string]::Empty 不同,我想保留这种区别。我还希望将$x 保留为[string] 类型,因为$x 仅作为字符串具有意义,并且该接口在其他地方使用。
- 如何让
$x在通过$null时输出为$null? - 还有其他方法可以告诉我
$x是从f内部传递的$null不是[string]::Empty?
更新 1
我正在尝试做的事情适用于其他类型。这是[int] 的相同概念:
function f {
param(
[System.Nullable[int]]$x
)
return $x
}
$r = f -x $null
在这种情况下,$r 确实是$null。 $x 可以是 $null 或 [int],但仅此而已。必须允许 any 对象对我来说似乎很奇怪,这样我才能传递 $null 或 [int]。
[System.Nullable[string]] 产生一个错误,归结为[System.Nullable[T]] 要求[T] 是一个值类型。 [string] 是引用类型,所以不起作用。
更新 2
似乎可以传递$null 而不会导致转换为任何类型的参数除了 [string]。我已经测试了以下内容:
function f { param([System.Nullable[int]]$x) $x }
function f { param([System.Nullable[System.DayOfWeek]]$x) $x }
function f { param([hashtable]$x) $x }
function f { param([array]$x) $x }
function f { param([System.Collections.Generic.Dictionary[string,int]]$x) $x }
function f { param([System.Collections.ArrayList]$x) $x }
function f { param([System.Collections.BitArray]$x) $x }
function f { param([System.Collections.SortedList]$x) $x }
function f { param([System.Collections.Queue]$x) $x }
function f { param([System.Collections.Stack]$x) $x }
将$null 传递给这些函数中的任何一个都会输出$null。 only 参数类型我还没有找到传递$null 而不进行转换的方法是[string]。
更新 3
PowerShell 在这方面的行为也与 C# 不一致。 C#中对应的函数如下:
public string f(string x)
{
return x;
}
调用f(null) 返回null。
更新 4
Apparently [NullString]::Value was intended to address this problem. 我似乎正在努力将 C# API 中的 null 传递给 string 参数。但是,[NullString]::Value 在 PowerShell 中转换为 [string]::empty,与 $null 相同。考虑以下代码:
function f {
param (
[AllowNull()]
[string]
$x
)
return $x
}
$r = f -x ([NullString]::Value)
$r.GetType().Name
执行该代码输出String。 $r 是 [string]::Empty,尽管 [NullString]::Value 已传递给 $x。
更新 5
The PowerShell team has indicated that this was by design:
这是设计使然,并且...改变行为将是一个巨大的突破性变化。
该线程涉及有关其背后原因的有趣讨论。我怀疑在做出决定时并未理解此行为的某些后果,因为该行为直接违反了PowerShell cmdlet "Strongly Encouraged Design Guideline" SD03,其中部分内容如下:
如果您的参数需要区分 3 个值:$true、$false 和“未指定”,则定义一个 Nullable 类型的参数。当 cmdlet 可以修改对象的布尔属性时,通常需要第三个“未指定”值。在这种情况下,“未指定”意味着不更改属性的当前值。
【问题讨论】:
-
您正在将参数转换为一个字符串,其中 [string] 在 $x 之前
-
没错。如果您不希望将某些内容转换为字符串:不要将其转换为字符串。
-
Nullable<T>doesn't work for strings,因为类型本身已经可以为空(原则上)。您面临的问题是 PowerShell 在将$null值传递给参数时将其转换为字符串,从而自动将该值转换为空字符串。 -
@AnsgarWiechers 我同意。当
[AllowNull()]和[string]都存在时,转换为[string]::empty似乎是一种奇怪的行为。 -
@JasonSnell “字符串不能为空,只能为空。” 我不认为这是一个准确的概括。例如,对于班级成员来说,情况并非如此。如果实例化
class c { [string]$x },则x是$null而不是[string]::Empty。
标签: string powershell parameters null