为什么这些代码构造会改变某些数据类型?

时间:2015-09-16 17:10:44

标签: powershell ternary-operator

前段时间我发现这个构造似乎很好地代替了PowerShell中的本地三元条件运算符:

$result = if ( $myBoolExpression ) { 'a' } else { 'b' }

但是我最近发现它的正确性与数据类型有关:对于某些数据类型,它会修改它返回的数据类型!

如果您运行以下测试代码,您将看到它适用于字符串:$ t1是'a',实际上它是一个字符串。 它适用于DateTime对象($ t2)。但是DataTable对象失败了($ t3和$ t4)。它似乎切掉了最外层的容器,并以一种时尚的方式返回下一层。使用$ t3,操作数是空数据表,因此$ t3获得$ null。使用$ t4,操作数是填充数据行的数据表,但$ t4是包含数据行的对象数组。我认为$ t3和$ t4都应该是DataTables。

问题1:为什么这个构造变形某些数据类型而不是其他数据?

问题2:为什么需要GetDataTable()中的最后一行? 我的意思是,如果它是一个简单的“return $ dataTable”而不是“return @(,($ dataTable))”那么它返回一个对象数组而不是DataTable!那么也许这是同一问题的另一个症状......?

(请注意,我知道还有其他方法可以模仿三元行为 - 尤其是Ternary operator in PowerShell - 但我不喜欢留下无法解释的问题: - )

function DoTest {

    $t1 = if ( $true) { 'a' } else { 'b' }
    $t1.GetType().Name # prints 'String'

    $obj1 = New-Object DateTime
    $obj2 = New-Object DateTime
    $t2 = if ( $true) { $obj1 } else { $obj2 }
    $t2.GetType().Name # prints 'DateTime'

    $obj1 = New-Object Data.DataTable
    $obj2 = New-Object Data.DataTable
    $t3 = if ( $true) { $obj1 } else { $obj2 }
    $t3 -eq $null # prints $true!
    # $t3.GetType().Name

    $obj1 = GetDataTable
    "obj1 is " + $obj1.GetType().Name
    $obj2 = GetDataTable
    $t4 = if ( $true) { $obj1 } else { $obj2 } # Question 1
    $t4.GetType().Name # prints 'Object[]'
    $t4[0].GetType().Name # prints 'DataRow'
}

DoTest 

此处显示补充GetDataTable函数。它仅用作创建非空DataTable的便捷函数:

function GetDataTable {
    $dataTable = New-Object Data.DataTable
    $Col = New-Object Data.DataColumn
    $Col.ColumnName = 'stuff'
    $dataTable.Columns.Add($Col )
    $row = $dataTable.NewRow()
    $row['stuff' ] = 'abc'
    $dataTable.Rows.Add($row )
    $row = $dataTable.NewRow()
    $row['stuff' ] = 'xyz'
    $dataTable.Rows.Add($row )
    return @(,($dataTable )) # Question 2-- just "return $dataTable" is insufficient
}

1 个答案:

答案 0 :(得分:0)

展开数组类型是powershell做的很多事情it can really bite you at the worst of times

我怀疑$null的解释是PowerShell's Extended Type System的类似部分。

不幸的是,它有时会变得错综复杂。