2017-08-16 17 views
3

考慮下面的代碼:如何防止綁定到參數時,將字符串參數從null更改爲空?

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

$r = f -x $null 

$null由到達return的時間轉換爲[string]::Empty$null[string]::Empty不同,我想保留這種區別。我還傾向於保留$x作爲[string]類型,因爲$x只具有字符串的含義,並且在其他地方使用該接口。

  1. 我怎樣才能讓$x出來爲$null當它傳遞$null
  2. 有沒有其他的方法我可以告訴$x已通過$null不是[string]::Emptyf裏面?

更新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沒有轉換是[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 nullstring參數。但是,[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個值來區分:$真,$假和「未指定」,然後定義一個Nullable類型的參數。當cmdlet可以修改對象的布爾屬性時,通常需要第三個「未指定」值。在這種情況下,「未指定」意味着不改變財產的當前價值。

+2

你鑄造參數轉換成字符串與前$ X –

+0

究竟[字符串。如果你不想將某些東西轉換爲字符串:不要將其轉換爲字符串。 –

+0

['可爲空'](https://msdn.microsoft.com/en-us/library/b3h38hb0.aspx)[不適用於字符串](https://stackoverflow.com/q/18852751/1630171 ),因爲類型本身已經是空的(原則上)。您面臨的問題是PowerShell在將字符串傳遞給參數時將「$ null」值轉換爲字符串,該參數將該值自動轉換爲空字符串。 –

回答

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

$r = f -x $null 

通過消除[string]和使用[AllowNull()]上面的功能現在可以讓你在一個空對象或空字符串傳遞。您可以使用$x.GetType和if語句來檢查類型,並確定$x是否爲空或空字符串。

+1

如果你想確保參數是'$ null'或者一個字符串,你可以驗證這個參數:'[ValidateScript($ _ -eq $ null -or $ _ -is [string])]''。您也可以將非空參數值轉換爲正文中的字符串,但這可能會產生不期望的結果(例如,當對象的字符串表示形式是其類型而不是其值時)。 –

+0

@AnsgarWiechers你應該做出該評論的答案。這遠遠是最有幫助的建議。 – alx9r

+0

Nah。這個答案已經解決了根本問題。我只是提出了一些微調。 –

2

默認情況下,[字符串]將默認值分配爲[string]::Empty,所以只要輸入函數f,參數定義就會將其轉換。
a。您可以更改參數爲[object]$x

[object]$newparamnull -eq $null 
[string]$newparamstring -eq [string]::Empty  

b。以前的更改將做的工作:

function f { 
    param (
     [AllowNull()] 
     [object] 
     $x) 
    if($x -eq $null) { 
     write-output "null" 
    } 
    elseif($x -eq [string]::empty){ 
     write-output "empty" 
    } 
    else {"other"} 
} 

測試:

f -x $null 
f -x [string]::empty 
f -x "aaa" 
+0

_「默認情況下,[字符串]將默認值分配爲[字符串] ::空」_我不認爲這是一個精確的概括。例如,對於類來說不是這樣。如果你實例化'class c {[string] $ x}','x'是'$ null'而不是'[string] :: Empty''。 – alx9r

相關問題