AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 708832
Accepted
Colyn1337
Colyn1337
Asked: 2015-07-28 08:48:18 +0800 CST2015-07-28 08:48:18 +0800 CST 2015-07-28 08:48:18 +0800 CST

如何转换为 ArrayList,在 param 块中预设数据,并返回为 ArrayList?

  • 772

由于我需要能够从数组中添加和删除项目,因此我需要将其转换为ArrayList与更常见的选项(、、、[string[]])[Array]相反的值$Var=@()。我还需要用数据对其进行预设,但函数的调用者需要能够根据需要更改预设。块中的预设Param()是必需的,因为另一个实体正在寻找预设数据。我尝试了几种变体,但这是最有意义的一种:

Function Test-Me{
    Param
    (
     $Properties = [System.Collection.ArrayList]@(
                   "red",
                   "blue",
                   "green")
    )
    $Properties.GetType()
    $Properties.Add("orange")
}

上面的内容很好,只是一旦有人调用Test-Me -Properties "Purple","Yellow","Black"该$Properties变量就成为标准Array类型(因此添加和删除方法不起作用)。

我尝试了更改我声明预设值的方式的方法。似乎预填充的行为是将类型转换为常规数组。我认为这是因为我使用@()的是预设,所以我也尝试()过。

这也不起作用:

Param
(
[System.Collection.ArrayList]
 $Properties = @("red",
                 "blue",
                 "green")
)

我有一个解决方法可以转换 Param 块之外的类型,它看起来像这样:

Function Test-Me{
    Param
    (
     [String[]]
     $Properties = @("red",
                     "blue",
                     "green")
    )

    if("Orange" -notin $Properties){
        [System.Collections.ArrayList]$Properties = $Properties
        $Properties.Add("orange")
    }
}

我觉得我应该能够ArrayList在 param 块中转换为 an 并用数据预设它,并以相同的 datatype 返回,但我想不通。如果有人这样做,或者找到了为什么它不起作用的文档,请回答。

powershell
  • 2 2 个回答
  • 5198 Views

2 个回答

  • Voted
  1. Best Answer
    Mathias R. Jessen
    2015-07-29T07:30:31+08:002015-07-29T07:30:31+08:00

    显式参数类型转换

    您发布的第二个示例(显式转换参数变量)是正确的方法:

    Function Test-Me {
        Param(
            [System.Collections.ArrayList]
            $Properties = @("red","blue","green")
        )
    
        Write-Host $Properties.GetType().FullName
    
        if("Orange" -notin $Properties){
            [void]$Properties.Add("orange")
        }
    
        $Properties
    }
    

    导致:

    PS C:\> Test-Me
    System.Collections.ArrayList
    red
    blue
    green
    orange
    
    PS C:\> Test-Me -Properties "one","two","three"
    System.Collections.ArrayList
    one
    two
    three
    orange
    

    输出类型

    不过,让我感到惊讶的一件事是,即使使用该[OutputType]属性,该函数也会输出一个常规数组(这实际上可能是一个错误预期的行为,请参阅下面的更新):

    Function Test-Me {
        [OutputType([System.Collections.ArrayList])]
        Param(
            [System.Collections.ArrayList]
            $Properties = @("red","blue","green")
        )
        
        if("Orange" -notin $Properties){
            [void]$Properties.Add("orange")
        }
    
        $Properties
    }
    

    仍然导致返回一个常规对象数组:

    PS C:\> (Test-Me).GetType()
    
    IsPublic IsSerial Name                                     BaseType
    -------- -------- ----                                     --------
    True     True     Object[]                                 System.Array
    

    更新(使用简单的解决方法)

    正如您对Connect 错误提交的评论中所展示的那样,PowerShell 故意枚举任何可枚举输出的项目,以便为管道提供一致的行为(从评论者 Derp McDerp 在 Connect 上窃取的伪 C#):

    if (returned_value is IEnumerable) {
        foreach (r in returned_value) {
            yield r;
        }
    } else {
        yield returned_value;
    }
    

    然后诀窍是将集合包装在一个单项数组中,导致 PowerShell 将其作为单个项进行管道传输(注意,before $Properties):

    Function Test-Me {
        [OutputType([System.Collections.ArrayList])]
        Param(
            [System.Collections.ArrayList]
            $Properties = @("red","blue","green")
        )
        
        if("Orange" -notin $Properties){
            [void]$Properties.Add("orange")
        }
    
        ,$Properties
    }
    

    现在,我们得到了正确类型的输出:

    PS C:\> (Test-Me).GetType()
    
    IsPublic IsSerial Name                                     BaseType
    -------- -------- ----                                     --------
    True     True     ArrayList                                System.Object
    
    • 3
  2. Kirk Munro
    2020-02-28T07:16:04+08:002020-02-28T07:16:04+08:00

    一位同事只是要我解释一些与此相关的细节,所以我认为与将来带着这个问题来这里的其他人分享一些补充信息可能是有益的。

    在 PowerShell 中,可以通过三种基本方式为变量赋值:

    # Loosely typed
    # Can be reassigned to anything without error
    $myVariable1 = @('Red','Green','Blue')
    
    # Type cast
    # Still loosely typed
    # Can still be reassigned to anything without issue
    $myVariable2 = [System.Collections.ArrayList]@('Red','Green','Blue')
    
    # Strongly typed
    # Can only be assigned objects of that type or objects that implicitly convert into that type
    [System.Collections.ArrayList]$myVariable3 = 'Red','Green','Blue'
    

    如果要确保变量(或函数参数)是特定类型,则必须使用强类型,就像使用$myVariable3. 这样做可以防止类型意外更改为其他内容(例如$myVariable3 = 42,将因错误而失败)。

    知道您可以使用Get-Variablecmdlet 识别变量何时为强类型是很有用的。例如,调用Get-Variable myVariable1,myVariable2,myVariable3 | Format-List Name,Value,Visibility,Options,Attributes会产生以下输出:

    Name       : myVariable1
    Value      : {Red, Green, Blue}
    Visibility : Public
    Options    : None
    Attributes : {}
    
    Name       : myVariable2
    Value      : {Red, Green, Blue}
    Visibility : Public
    Options    : None
    Attributes : {}
    
    Name       : myVariable3
    Value      : {Red, Green, Blue}
    Visibility : Public
    Options    : None
    Attributes : {System.Management.Automation.ArgumentTypeConverterAttribute}
    

    myVariable3请注意,除了变量在属性中具有属性之外,这些都是相同的Attributes。AnArgumentTypeConverterAttribute被添加到任何强类型的变量中,并且该属性将确保变量保持相同的类型,无论您将其分配给什么。

    了解变量赋值的工作原理,以及如何像 Mathias上面指出的那样完整地返回集合,可以更轻松地在 PowerShell 中处理数据。

    • 0

相关问题

  • 资源锁和电源外壳

  • 脚本 - 如何断开远程桌面会话?

  • 如何限制向通讯组发送到外部地址?

  • Powershell对值与数组的作用不同?

  • Windows Powershell Vim 键绑定

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve