簡體   English   中英

將null傳遞給函數的必需參數

[英]Passing null to a mandatory parameter to a function

實際上我的問題歸結為:

我不能有一個帶有強制參數的函數,並將$ null傳遞給該參數:

Function Foo
{
    Param
    (
        [Parameter(Mandatory = $true)][string] $Bar
    )

    Write-Host $Bar
}

Foo -Bar $null

這將返回foo : Cannot bind argument to parameter 'Bar' because it is an empty string.

同樣,使它成為一個數組也失敗了:

Function Foo
{
    Param
    (
        [Parameter(Mandatory = $true)][string[]] $Bar
    )

    Write-Host $Bar
}

Foo -Bar 1, 2 

> 1 2

Foo -Bar 1, 2, $null

> foo : Cannot bind argument to parameter 'Bar' because it is an empty string.

在編程術語中,完全可以使用一個接受強制可為空參數的函數,但我無法在PowerShell中找到這樣做的方法。

我該怎么做?

您應該能夠為[string]參數使用[AllowEmptyString()]參數屬性和/或為其他類型使用[AllowNull()]參數屬性。 我已經從您的示例中為函數添加了[AllowEmptyString()]屬性:

Function Foo {
    Param
    (
        [Parameter(Mandatory = $true)]
        [AllowEmptyString()]  <#-- Add this #>
        [string] $Bar
    )

    Write-Host $Bar
}

Foo -Bar $null

有關詳細信息,請查看about_Functions_Advanced_Parameters幫助主題。

請注意,在強制參數的參數綁定期間,PowerShell會將$ null值強制轉換為某些類型的實例,例如, [string] $null變為空字符串, [int] $null變為0.要繞過它,您有一個幾個選項:

  • 刪除參數類型約束。 您可以在代碼中檢查$ null,然后轉換為所需的類型。
  • 使用System.Nullable(請參閱其他答案)。 這僅適用於值類型。
  • 重新考慮函數設計,以便您沒有應該允許null的必需參數。

正如Rohn Edwards的回答中所提到的, [AllowNull()]和/或[AllowEmptyString()]是解決方案的一部分,但需要考慮一些事項。

盡管問題中給出的示例是帶有類型字符串,但標題上的問題是如何將null傳遞給強制參數,而不提及類型,因此我們需要稍微擴展答案。

首先讓我們看看PowerShell如何處理為某些類型分配$ null:

PS C:\> [int] $null
0
PS C:\> [bool] $null
False
PS C:\> [wmi] $null
PS C:\>
PS C:\> [string] $null

PS C:\>

分析結果:

  • $null傳遞給[int]返回值為0[int]對象
  • $null傳遞給[bool]返回值為False[bool]對象
  • $null傳遞給[wmi]返回......沒有。 它根本不會創建一個對象。 這可以通過執行([wmi] $null).GetType()來確認,它會拋出錯誤
  • $null傳遞給[string]返回一個值為'' (空字符串)的[string]對象。 這可以通過執行([string] $null).GetType()([string] $null).Length ([string] $null).GetType()來確認。

那么,如果我們有一個非強制性[int]參數的函數,如果我們不傳遞該參數,它將具有什么值? 讓我們檢查:

Function Foo {
    Param (
        [int] $Bar
    )
    Write-Host $Bar
}

Foo
> 0

顯然,如果它是[bool]該值為False ,如果它是[string]該值將為''

因此,當我們有大多數標准類型的強制參數並且我們將其賦值為$null ,我們不會獲得$null ,而是獲得該類型的“默認值”。

例:

Function Foo {
    Param (
        [Parameter(Mandatory = $true)][int] $Bar
    )
    Write-Host $Bar
}

Foo -Bar $null
> 0

注意那里根本沒有[AllowNull()] ,但它仍然返回0

[string]略有不同,因為它不允許強制參數上的空字符串,這就是問題中的示例失敗的原因。 [AllowNull()]也沒有修復它,因為空字符串與$null ,所以我們需要使用[AllowEmptyString()] 其他任何事情都會失敗。

那么, [AllowNull()]在哪里發揮作用,以及如何將“真正的” $null傳遞給int,bool,wmi等?

int和bool都不是可空類型,所以為了向它們傳遞“真正的” $null ,你需要使它們可以為空:

Function Foo {
    Param (
        [Parameter(Mandatory = $true)][AllowNull()][System.Nullable[int]] $Bar
    )
    Write-Host $Bar
}

這允許將“true” $null傳遞給int,顯然在調用Write-Host它會將$null轉換為字符串,這意味着我們最終會再次使用'' ,所以它仍會輸出一些東西,但它是一個“true” $null被傳遞。

[wmi] (或.NET類)這樣的可空類型更容易,因為它們從一開始就已經可以為空,所以它們不需要可以為空,但仍然需要[AllowNull()]

至於使一個[string]真正可以為空,那個仍然可以逃避我,就像試圖做的那樣:

[System.Nullable[string]]

返回錯誤。 很可能是因為system.string已經可以為空了,盡管PowerShell似乎沒有這樣看。

編輯

我只是注意到了

[bool] $null

被強迫進入False ,做......

Function Foo {
    Param (
        [bool] $Bar
    )
    $Bar
}

Foo -Bar $null

拋出以下錯誤:

Foo : Cannot process argument transformation on parameter 'Bar'. Cannot convert value "" to type "System.Boolean".

這是非常離奇的,更是如此,因為在上面的函數中使用[switch]而不是[bool]

我想你錯過了“,”來分離參數。

Param (
    [string]$ObjectName,
    [int]$ObjectId,
    [wmi]$Object
)

首先,添加AllowNull屬性:

Function Foo
{
    Param
    (
        [Parameter(Mandatory = $true)][AllowNull()][string] $Bar
    )

    Write-Host $Bar
}

然后,當您調用該函數時,請注意當用於[string]$null變為空字符串,而不是空引用。 因此(自PowerShell 3(2012))使用[NullString]::Value如下所示:

Foo -Bar ([NullString]::Value)

請參閱System.Management.Automation.Language.NullString文檔


編輯:從調用站點,這似乎工作,但是當您到達函數內的Write-Host cmdlet時, $Bar將再次變為空字符串。 見下面的評論。 我們必須得出結論,PowerShell堅持字符串必須是這樣的。 請注意, NullString (在其他情況下對我有用)在其文檔中僅承諾在將null 傳遞給.NET方法”時會有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM