gpt4 book ai didi

.net - @($null) 和 $null 的区别

转载 作者:行者123 更新时间:2023-12-03 14:35:23 24 4
gpt4 key购买 nike

我有一些 PowerShell 代码,我在其中调用一个 .NET 方法,该方法希望将一个类作为参数传递。

该方法接受一个空值作为参数,在 C# 中,您将按如下方式调用它:

var T = New Foo(null)

如果将其转换为 PowerShell,可以尝试:

$T = New-Object Foo($null)

但是返回以下错误

New-Object : Constructor not found. Cannot find an appropriate constructor for type Foo

有趣的是,如果我这样调用它,会返回完全相同的错误:

$T = New-Object Foo

所以第一个问题是为什么? .NET 是否将 $null 视为缺少某物,与 .NET 中的类型 null 相对?这就是上面两条指令返回相同错误的原因吗?

现在,我找到了解决这个问题的方法如下:

$T = New-Object Foo(@($null))

这工作得很好,但是......为什么?

(@($Null)).GetType() 返回 object[]

(@()).GetType() 也返回 object[],但如果我运行:

$T = New-Object Foo(@())

我仍然得到:

New-Object : Constructor not found. Cannot find an appropriate constructor for type Foo

那么,第二个问题:@()、@($null) 和 $null 之间有什么区别?

另外,最后一个问题,这是我不明白的另一件事。

假设我有另一个 .NET 方法作为 Bar(string, Foo)

如果我调用:

$B = New-Object Bar("s", $null)

这很好用,无需将其转换为对象[] 或类似的东西。

那么第三个也是最后一个问题是:为什么参数个数会影响是否需要作为数组传递?

我的猜测是,如果我要将它转换成一个数组,我会称它为

$B = New-Object Bar(@("s", $null))

这意味着即使该方法需要两个参数,我只将一个作为对象数组传递给它,然后它会自动将每个数组项映射到参数上,但这仍然不能完全提供答案前两个问题:)

编辑

我知道 @() 是一个空数组,而 @($null) 是一个包含一个恰好为 null 的元素的数组,所以这不是我要问的。

但是,如果调用:

$T = New-Object Foo($null)

使 Foo 的构造函数看不到传递的参数,为什么调用 @() 与调用 @($null) 不同?当然,在这种情况下,@($null) 应该与 @() 相同,因为在 .NET 方法中缺少参数。

为什么 $null 有时有意义,有时却毫无意义?

最佳答案

根据您的编辑,您已经很好地理解了 $null 和 @($null) 之间的区别。

与对 .Net 方法的正常调用不同,调用构造函数需要先调用 New-Object cmdlet。 New-Object 的语法是:

New-Object [-TypeName] <string> [[-ArgumentList] <Object[]>] [-Property <IDictionary>]

让我们想一想 New-Object 是如何工作的。使用反射,New-Object 将调用 TypeName.GetConstructors() 并找到可以接受 n 个参数的候选构造函数,其中 n 是 ArgumentList 中参数的数量。

如果您这样调用 New-Object:

New-Object -TypeName Foo

那么 ArgumentList 的值为 $null。您没有传递 $null,但这就是它的值(value)。如果 ArgumentList 为 $null,则没有参数。在此示例中,很明显,您没有指定 -ArgumentList。如果你写:

New-Object -TypeName Foo -ArgumentList $null

这以相同的最终结果结束——没有参数列表。 ArgumentList 需要一个 [object[]],$null 是 [object[]] 的完全有效值,但这意味着没有参数。

如果你写:

New-Object -TypeName Foo -ArgumentList @($null)

现在您正在传递一个具有单个值的 [object[]],值 $null,并且一切都如您所愿。

这无疑令人困惑,但有助于思考如何实现自己的 C# 函数来调用另一个函数并接受参数数组。如果您的参数数组为空,则您不会收到额外的参数。

在某些情况下,New-Object 可能更加令人困惑。我个人被重载的构造函数绊倒了,一个接受数组,另一个接受多个参数。在 C# 中,构造函数类似于:

Foo(object[] array);   // #1
Foo(string s, int i); // #2

我错误地尝试调用构造函数#1:

New-Object -TypeName Foo -ArgumentList @($array)

这会调用构造函数#2,因为 New-Object 总是期望 [object[]] 传递多个参数,而您很少希望使用单个数组参数调用构造函数。正确的 PowerShell 应该是:

New-Object -TypeName Foo -ArgumentList (,$array)

由于这种混淆,我在 PowerShell V5 中添加了一种调用构造函数的新方法。现在可以作为非常早的预览版 ( http://www.microsoft.com/en-us/download/details.aspx?id=42936 ) 使用,语法看起来像静态方法调用:

[Foo]::new($name, $count)

使用这种新语法,调用构造函数不再令人困惑,而且作为附带好处,它也比调用 New-Object 快一个数量级。

编辑:我用重载构造函数更正了示例。

关于.net - @($null) 和 $null 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25360193/

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