Novos recursos de linguagem no PowerShell 5.0New language features in PowerShell 5.0

O PowerShell 5.0 introduz os seguintes novos elementos de linguagem no Windows PowerShell:PowerShell 5.0 introduces the following new language elements in Windows PowerShell:

Palavra-chave classClass keyword

A palavra-chave class define uma nova classe.The class keyword defines a new class. Este é um tipo real do .NET Framework.This is a true .NET Framework type. Membros de classe são públicos, mas somente públicos dentro do escopo do módulo.Class members are public, but only public within the module scope. Não é possível se referir ao nome de tipo como uma cadeia de caracteres (por exemplo, New-Object não funciona), e nesta versão, não é possível usar um literal de tipo (por exemplo, [MyClass]) fora do arquivo de script/módulo no qual a classe é definida.You can't refer to the type name as a string (for example, New-Object doesn't work), and in this release, you can't use a type literal (for example, [MyClass]) outside the script/module file in which the class is defined.

class MyClass
{
    ...
}

Palavra-chave Enum e enumeraçõesEnum keyword and enumerations

O suporte à palavra-chave enum for adicionado, que usa uma nova linha como o delimitador.Support for the enum keyword has been added, which uses newline as the delimiter. Limitações atuais: não é possível definir um enumerador em relação a si mesmo, mas é possível inicializar um enum em relação a outro enum, conforme mostrado no exemplo a seguir.Current limitations: you cannot define an enumerator in terms of itself, but you can initialize an enum in terms of another enum, as shown in the following example. Além disso, atualmente, o tipo base não pode ser especificado; ele é sempre [int].Also, the base type cannot currently be specified; it is always [int].

enum Color2
{
    Yellow = [Color]::Blue
}

Um valor do enumerador deve ser uma constante de tempo de análise; não é possível defini-lo como o resultado de um comando invocado.An enumerator value must be a parse time constant; you cannot set it to the result of an invoked command.

enum MyEnum
{
    Enum1
    Enum2
    Enum3 = 42
    Enum4 = [int]::MaxValue
}

Enums dão suporte a operações aritméticas, conforme mostrado no exemplo a seguir.Enums support arithmetic operations, as shown in the following example.

enum SomeEnum { Max = 42 }
enum OtherEnum { Max = [SomeEnum]::Max + 1 }

Import-DscResourceImport-DscResource

Import-DscResource agora é uma palavra-chave dinâmica real.Import-DscResource is now a true dynamic keyword. O PowerShell analisa o módulo raiz do módulo especificado, pesquisando classes que contêm o atributo DscResource.PowerShell parses the specified module’s root module, searching for classes that contain the DscResource attribute.

ImplementingAssemblyImplementingAssembly

Um novo campo, ImplementingAssembly, foi adicionado a ModuleInfo.A new field, ImplementingAssembly, has been added to ModuleInfo. Ele é definido como o assembly dinâmico criado para um módulo de script, caso o script defina classes, ou como o assembly carregado para módulos binários.It is set to the dynamic assembly created for a script module if the script defines classes, or the loaded assembly for binary modules. Ele não é definido quando ModuleType = Manifest.It is not set when ModuleType = Manifest.

A reflexão sobre o campo ImplementingAssembly descobre recursos em um módulo.Reflection on the ImplementingAssembly field discovers resources in a module. Isso significa que é possível descobrir recursos escritos no PowerShell ou em outras linguagens gerenciadas.This means you can discover resources written in either PowerShell or other managed languages.

Campos com inicializadores:Fields with initializers:

[int] $i = 5

Há suporte para static; ele funciona como um atributo, assim como as restrições de tipo; portanto, pode ser especificado em qualquer ordem.Static is supported; it works like an attribute, as do the type constraints, so it can be specified in any order.

static [int] $count = 0

Um tipo é opcional.A type is optional.

$s = "hello"

Todos os membros são públicos.All members are public.

Construtores e instanciaçãoConstructors and instantiation

As classes do Windows PowerShell podem ter construtores; eles têm o mesmo nome que a classe.Windows PowerShell classes can have constructors; they have the same name as their class. Os construtores podem ser sobrecarregados.Constructors can be overloaded. Há suporte para construtores estáticos.Static constructors are supported. As propriedades com expressões de inicialização são inicializadas antes da execução de qualquer código em um construtor.Properties with initialization expressions are initialized before running any code in a constructor. As propriedades estáticas são inicializadas antes do corpo de um construtor estático, e as propriedades de instância são inicializadas antes do corpo do construtor não estático.Static properties are initialized before the body of a static constructor, and instance properties are initialized before the body of the non-static constructor. Atualmente, não há nenhuma sintaxe para chamar um construtor de outro construtor [como a sintaxe do C# ": this()"].Currently, there is no syntax for calling a constructor from another constructor (like the C# syntax ": this()"). A solução alternativa é definir um método comum de Init.The workaround is to define a common Init method.

Veja a seguir as maneiras de criar uma instância de classes nesta versão.The following are ways of instantiating classes in this release.

Criando uma instância usando o construtor padrão.Instantiating by using the default constructor. Observe que não há suporte para New-Object nesta versão.Note that New-Object is not supported in this release.

$a = [MyClass]::new()

Chamando um construtor com um parâmetroCalling a constructor with a parameter

$b = [MyClass]::new(42)

Passando uma matriz para um construtor com vários parâmetrosPassing an array to a constructor with multiple parameters

$c = [MyClass]::new(@(42,43,44), "Hello")

Nesta versão, New-Object não funciona com classes definidas no Windows PowerShell.In this release, New-Object does not work with classes defined in Windows PowerShell. Além disso, nesta versão, o nome de tipo é visível apenas lexicalmente, o que significa que ele não é visível fora do módulo ou do script que define a classe.Also for this release, the type name is only visible lexically, meaning it is not visible outside of the module or script that defines the class. As funções podem retornar instâncias de uma classe definida no Windows PowerShell, e as instâncias funcionam bem fora do módulo ou do script.Functions can return instances of a class defined in Windows PowerShell, and instances work well outside of the module or script.

Get-Member -Static lista os construtores, para que seja possível exibir sobrecargas como qualquer outro método.Get-Member -Static lists constructors, so you can view overloads like any other method. O desempenho dessa sintaxe também é consideravelmente mais rápido do que o de New-Object.The performance of this syntax is also considerably faster than New-Object.

O método pseudoestático chamado new funciona com tipos do .NET, conforme mostrado no exemplo a seguir.The pseudo-static method named new works with .NET types, as shown in the following example.

[hashtable]::new()

Agora você pode ver as sobrecargas do construtor com Get-Member, ou conforme mostrado neste exemplo:You can now see constructor overloads with Get-Member, or as shown in this example:

PS> [hashtable]::new
OverloadDefinitions
-------------------
hashtable new()
hashtable new(int capacity)
hashtable new(int capacity, float loadFactor)

MétodosMethods

Um método de classe do Windows PowerShell é implementado como um ScriptBlock que tem apenas um end block.A Windows PowerShell class method is implemented as a ScriptBlock that has only an end block. Todos os métodos são públicos.All methods are public. Veja a seguir um exemplo de definição de um método chamado DoSomething.The following shows an example of defining a method named DoSomething.

class MyClass
{
    DoSomething($x)
    {
        $this._doSomething($x) # method syntax
    }
    private _doSomething($a) {}
}

Invocação de método:Method invocation:

$b = [MyClass]::new()
$b.DoSomething(42) 

Também há suporte para métodos sobrecarregados – ou seja, aqueles que têm o mesmo nome que um método existente, mas que são diferenciados por seus valores especificados.Overloaded methods--that is, those that are named the same as an existing method, but differentiated by their specified values--are also supported.

PropriedadesProperties

Todas as propriedades são públicas.All properties are public. As propriedades exigem uma nova linha ou um ponto-e-vírgula.Properties require either a newline or semicolon. Se nenhum tipo de objeto for especificado, o tipo de propriedade será o objeto.If no object type is specified, the property type is object.

As propriedades que usam atributos de validação ou atributos de transformação de argumento (por exemplo, [ValidateSet("aaa")]) funcionam como esperado.Properties that use validation attributes or argument transformation attributes (e.g. [ValidateSet("aaa")]) work as expected.

HiddenHidden

Uma nova palavra-chave, Hidden, foi adicionada.A new keyword, Hidden, has been added. Hidden pode ser aplicado a propriedades e métodos (incluindo construtores).Hidden can be applied to properties and methods (including constructors).

Membros ocultos são públicos, mas não aparecem na saída de Get-Member, a menos que o parâmetro -Force seja adicionado.Hidden members are public, but do not appear in the output of Get-Member unless the -Force parameter is added.

Membros ocultos não são incluídos durante o preenchimento de tabulação ou uso do IntelliSense, a menos que o preenchimento ocorra na classe que define o membro oculto.Hidden members are not included when tab completing or using Intellisense unless the completion occurs in the class defining the hidden member.

Um novo atributo, System.Management.Automation.HiddenAttribute, foi adicionado, para que o código do C# possa ter a mesma semântica dentro do Windows PowerShell.A new attribute, System.Management.Automation.HiddenAttribute has been added so that C# code can have the same semantics within Windows PowerShell.

Tipos de retornoReturn types

O tipo de retorno é um contrato; o valor retornado é convertido para o tipo esperado.Return type is a contract; the return value is converted to the expected type. Se nenhum tipo de retorno for especificado, o tipo de retorno será nulo.If no return type is specified, the return type is void. Não há nenhum streaming de objetos; os objetos não podem ser gravados no pipeline, seja intencionalmente ou por engano.There is no streaming of objects; objects cannot be written to the pipeline either intentionally or by accident.

AtributosAttributes

Dois novos atributos, DscResource e DscProperty foram adicionados.Two new attributes, DscResource and DscProperty have been added.

Escopo léxico de variáveisLexical scoping of variables

Apresentamos a seguir um exemplo de como o escopo léxico funciona nesta versão.The following shows an example of how lexical scoping works in this release.

$d = 42 # Script scope

function bar
{
    $d = 0 # Function scope
    [MyClass]::DoSomething()
}

class MyClass
{
    static [object] DoSomething()
    {
        return $d # error, not found dynamically
        return $script:d # no error
        $d = $script:d
        return $d # no error, found lexically
    }
}

$v = bar
$v -eq $d # true

Exemplo de ponta a pontaEnd-to-End Example

O exemplo a seguir cria várias classes novas e personalizadas para implementar uma DSL (linguagem de folha de estilos dinâmica) em HTML.The following example creates several new, custom classes to implement an HTML dynamic style sheet language (DSL). Em seguida, o exemplo adiciona funções auxiliares para criar tipos específicos de elementos como parte da classe de elemento, como estilos de título e tabelas, já que os tipos não podem ser usados fora do escopo de um módulo.Then, the example adds helper functions to create specific element types as part of the element class, such as heading styles and tables, because types cannot be used outside the scope of a module.

# Classes that define the structure of the document
#
class Html
{
    [string] $docType
    [HtmlHead] $Head
    [Element[]] $Body

    [string] Render()
    {
        $text = "<html>`n<head>`n"
        $text += $this.Head
        $text += "`n</head>`n<body>`n"
        $text += $this.Body -join "`n" # Render all of the body elements
        $text += "</body>`n</html>"
        return $text
    }
    [string] ToString() { return $this.Render() }
}

class HtmlHead
{
    $Title
    $Base
    $Link
    $Style
    $Meta
    $Script
    [string] Render() { return "<title>$($this.Title)</title>" }
    [string] ToString() { return $this.Render() }
}

class Element
{
    [string] $Tag
    [string] $Text
    [hashtable] $Attributes
    [string] Render() {
        $attributesText= ""
        if ($this.Attributes)
        {
            foreach ($attr in $this.Attributes.Keys)
            {
                #BUGBUG - need to validate keys against attribute
                $attributesText += " $attr=`"$($this.Attributes[$attr])\`""
            }
        }
        return "<$($this.tag)${attributesText}>$($this.text)</$($this.tag)>`n"
    }
[string] ToString() { return $this.Render() }
}

#
# Helper functions for creating specific element types on top of the classes.
# These are required because types aren’t visible outside of the module.
#

function H1 { [Element] @{ Tag = "H1" ; Text = $args.foreach{$_} -join " " }}
function H2 { [Element] @{ Tag = "H2" ; Text = $args.foreach{$_} -join " " }}
function H3 { [Element] @{ Tag = "H3" ; Text = $args.foreach{$_} -join " " }}
function P { [Element] @{ Tag = "P" ; Text = $args.foreach{$_} -join " " }}
function B { [Element] @{ Tag = "B" ; Text = $args.foreach{$_} -join " " }}
function I { [Element] @{ Tag = "I" ; Text = $args.foreach{$_} -join " " }}
function HREF
{
    param (
        $Name,
        $Link
    )
    return [Element] @{
        Tag = "A"
        Attributes = @{ HREF = $link }
        Text = $name
    }
}
function Table
{
    param (
    [Parameter(Mandatory)]
    [object[]]
        $Data,
    [Parameter()]
    [string[]]
        $Properties = "*",
    [Parameter()]
    [hashtable]
        $Attributes = @{ border=2; cellpadding=2; cellspacing=2 }
    )
$bodyText = ""
# Add the header tags
$bodyText += $Properties.foreach{TH $_}
# Add the rows
$bodyText += foreach ($row in $Data)
    {
        TR (-join $Properties.Foreach{ TD ($row.$\_) } )
    }

    $table = [Element] @{
        Tag = "Table"
        Attributes = $Attributes
        Text = $bodyText
    }
$table
}
function TH { ([Element] @{ Tag = "TH" ; Text = $args.foreach{$_} -join " " }) }
function TR { ([Element] @{ Tag = "TR" ; Text = $args.foreach{$_} -join " " }) }
function TD { ([Element] @{ Tag = "TD" ; Text = $args.foreach{$_} -join " " }) }
function Style

{
    return [Element] @{
        Tag = "style"
        Text = "$args"
    }
}

# Takes a hash table, casts it to and HTML document
# and then returns the resulting type.
#
function Html ([HTML] $doc) { return $doc }