gpt4 book ai didi

string - 绑定(bind)到参数时,如何防止字符串参数从 null 更改为空?

转载 作者:行者123 更新时间:2023-12-02 08:27:54 29 4
gpt4 key购买 nike

考虑以下代码:

function f {
param (
[AllowNull()]
[string]
$x
)
return $x
}

$r = f -x $null
$null转换为 [string]::Empty到时候 return到达了。 $null不同于 [string]::Empty我想保留这种区别。我也更愿意保留 $x如类型 [string]因为 $x仅作为字符串有意义,并且该接口(interface)在其他地方使用。
  • 我该如何制作 $x出来为 $null当它通过时$null ?
  • 有没有其他方法可以告诉我 $x已通过 $null不是 [string]::Empty从内部 f ?


  • 更新 1

    我正在尝试做的事情适用于其他类型。这是 [int] 的相同概念:
    function f { 
    param(
    [System.Nullable[int]]$x
    )
    return $x
    }

    $r = f -x $null

    在那种情况下 $r确实是 $null . $x可以是 $null[int]但没有别的。必须允许任何对象才能传递 $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。我还没有找到传递的唯一参数类型 $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.我好像工作通过 nullstring C# API 中的参数。然而, [NullString]::Value转换为 [string]::empty在 PowerShell 中与 $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 :

    This is by design and ... changing the behavior would be a massive breaking change.



    该线程涉及有关其背后推理的有趣讨论。我怀疑在做出决定时并未理解这种行为的某些后果,因为该行为直接违反了 PowerShell cmdlet "Strongly Encouraged Design Guideline" SD03部分内容如下:

    If your parameter needs to differentiate between 3 values: $true, $false and “unspecified”, then define a parameter of type Nullable. The need for a 3rd, "unspecified" value typically occurs when the cmdlet can modify a Boolean property of an object. In this case "unspecified" means to not change the current value of the property.

    最佳答案

    总结和补充问题、答案和评论中的信息:
    tl;博士 :
    最好不要对抗 PowerShell 不允许的设计 [string]变量为 $null ,并限制使用 [NullString]::Value调用 .NET 方法。

  • PowerShell 转换 $null'' (空字符串)当它被分配给 [string] 时-typed [参数] 变量,参数变量也默认为 '' .
  • 唯一的异常(exception)是使用未初始化的 [string] PSv5+ 自定义类中的属性,正如 alxr9(OP)指出的那样:class c { [string] $x }; $null -eq ([c]::new()).x确实产生 $True暗示该属性(property).x包含 $null .然而,这个异常很可能是偶然的,probably a bug ,考虑到当您使用 $null 初始化属性时或分配 $null稍后,转换为''再次开始;同样,使用 return $null来自 [string] -typed 方法输出 '' .
  • 除了异常(exception),PowerShell 的行为与 C# 字符串变量/参数不同,您可以为其分配/传递 null直接,默认为 null在某些情况下。 string是 .NET 引用类型,此行为适用于所有引用类型。
    (由于引用类型实例本身可以包含 null ,因此不需要通过 System.Nullable`1 单独的可为空的包装器,这确实不受支持(它仅适用于值类型)。

  • 如问题(更新 5)中所述,PowerShell 与 C# 行为的背离是由 (design, and it is changing it is not an option 仅出于向后兼容性的原因。
  • [NullString]::Value 在 v3 中专门针对 引入允许通过 nullstring .NET 方法的参数 - 虽然没有明确阻止或阻止在纯 PowerShell 代码中使用,但更新 4 中的意外行为和核心 PowerShell 团队成员(见下文)的评论表明,这种使用是没有预料到的。
  • 警告 : 虽然可以使用 [NullString]::Value在纯 PowerShell 代码中,考虑到 ,可能存在超出下面讨论的陷阱。使用 [NullString]::Value从未打算在调用 .NET 方法的上下文之外使用 ;至 quote a core member of the PowerShell team :


  • Parameters to C# methods was the target scenario for [NullString]::Value, and I will say that might be the only reasonable scenario.


  • A 解决方法 是到 将您的(参数)变量输入为 [object] 或到 不限制类型 完全一样。这样的变量愉快地接受 $null ,但请注意 您可能需要字符串化(转换为 [string] )非 $null重视自己 (尽管 PowerShell 在显式或隐式字符串上下文中自动为您执行此操作) - 请参阅下面的倒数第二个代码示例。

  • 如果,尽管有上述建议,您确实需要 [string]可以传递的参数变量$null至通过 [NullString]::Value ,就像您问题中的更新 4 一样,有一个 - 晦涩的 - 解决方法 the optimization bug由于 PetSerAl 的侦查,这会阻止您的代码工作:
    function f {
    param (
    [string] $x
    )
    # Workaround; without this, even passing [NullString]::Value
    # returns '' rather than $null
    if ($False) { Remove-Variable }
    return $x
    }

    $r = f -x ([NullString]::Value)
    $r.GetType().Name # now fails, because $r is $null
    注意分配/传递时 [NullString]::Value[string] -typed [参数] 变量,立即转换为 $null (在参数变量的情况下,仅当错误得到修复或解决方法到位时)。
    然而,曾经 $null已经以这种方式成功存储在变量中,它显然可以这样传递(同样,只有在错误得到修复或解决方法到位时)。

    如果您不想依赖解决方法/等待修复和/或不想给调用者带来负担 [NullString]::Value而不是 $null ,您可以通过 Curios 建立答案和 Jason Schnell , 依赖于 使用无类型(隐式 [object] 类型)或显式 [object] -typed 参数,可以接受 $null原样 :
    function f {
    param (
    [AllowNull()] # Explicitly allow passing $null.
    # Note: Strictly speaking only necessary with [Parameter(Mandatory=$True)]
    $x # Leave the parameter untyped (or use [object]) so as to retain $null as-is
    )

    # Convert $x to a type-constrained [string] variable *now*:
    if ($null -eq $x) {
    # Make $x contain $null, despite being [string]-typed
    [string] $x = [NullString]::Value
    } else {
    # Simply convert any other type to a string.
    [string] $x = $x
    }

    # $x is now a bona fide [string] variable that can be used
    # as such even in .NET method calls.

    return $x
    }
    有点麻烦,但是可以让调用者通过 $null直接(或任何字符串,或将转换为字符串的任何其他实例的类型)。
    一个轻微的缺点是这种方法不允许您通过由参数的特定类型选择的不同参数集在同一位置定义位置参数。

    最后,值得一提的是 如果足以检测何时省略了(非强制性)参数,您可以检查 $PSBoundParameters :
    function f {
    param (
    [string] $x
    )

    if ($PSBoundParameters.ContainsKey('x')) { # Was a value passed to parameter -x?
    "-x argument was passed: $x"
    } else {
    "no -x argument passed."
    }
    }
    如上所述,这仅适用于省略情况(因此根本不适用于强制性参数)。如果您通过 $null ,通常转换为 ''开始,你将无法区分通过 $null'' .
    (尽管如果您添加了上述解决方法/等待错误修复,您可以再次传递 [NullString]::Value 以有效传递 $null ,甚至使用 [NullString]::Value 作为参数默认值。)

    关于string - 绑定(bind)到参数时,如何防止字符串参数从 null 更改为空?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45720150/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com