Compartilhar via


Refatorar em funções puras (LINQ to XML)

Um aspecto importante de transformações e puras é aprender como o código do refatorar usando funções puras.

Observação

A nomenclatura comuns em programação funcional é que você refatora programa usando funções puras. No Visual Basic e C++, isso alinha com o uso das funções em linguagens respectivos. No entanto, em C#, as funções são chamadas métodos. Para fins desta discussão, uma função pura é implementada como um método em C#.

Conforme observado anteriormente nesta seção, uma função pura tem duas características úteis:

  • Não tem efeito colateral. A função não altera quaisquer variáveis ou os dados de qualquer tipo fora da função.
  • É consistente. Dado o mesmo conjunto de dados de entrada, sempre retornará o mesmo valor de saída.

Uma maneira de fazer a transição para programação funcional é o código existente do refatorar para eliminar efeitos colaterais desnecessários e dependências externas. Dessa maneira, você pode criar versões puras de função do código existente.

Este artigo descreve o que é uma função pura e o que não é. O tutorial Tutorial: Manipular conteúdo em um documento WordprocessingML mostra como manipular um documento WordprocessingML e inclui dois exemplos de como refatorar usando uma função pura.

Os seguintes exemplos contrastam duas funções não puras e uma função pura.

Exemplo: implementar uma função não pura que altera um membro de classe estática

No seguinte código, a função HyphenatedConcat não é uma função pura, pois ela modifica o membro da classe estática aMember:

public class Program
{
    private static string aMember = "StringOne";

    public static void HyphenatedConcat(string appendStr)
    {
        aMember += '-' + appendStr;
    }

    public static void Main()
    {
        HyphenatedConcat("StringTwo");
        Console.WriteLine(aMember);
    }
}
Module Module1
    Dim aMember As String = "StringOne"

    Public Sub HyphenatedConcat(ByVal appendStr As String)
        aMember = aMember & "-" & appendStr
    End Sub

    Sub Main()
        HyphenatedConcat("StringTwo")
        Console.WriteLine(aMember)
    End Sub
End Module

Esse exemplo gera a saída a seguir:

StringOne-StringTwo

Observe que é irrelevante se os dados modificados têm acesso a public ou private ou são um membro de static, de shared ou um membro de instância. Uma função pura não altera quaisquer dados fora da função.

Exemplo: implementar uma função não pura que altera um parâmetro

Além disso, a versão a seguir dessa mesma função não é pura porque modifica o conteúdo do seu parâmetro, sb.

public class Program
{
    public static void HyphenatedConcat(StringBuilder sb, String appendStr)
    {
        sb.Append('-' + appendStr);
    }

    public static void Main()
    {
        StringBuilder sb1 = new StringBuilder("StringOne");
        HyphenatedConcat(sb1, "StringTwo");
        Console.WriteLine(sb1);
    }
}
Module Module1
    Public Sub HyphenatedConcat(ByVal sb As StringBuilder, ByVal appendStr As String)
        sb.Append("-" & appendStr)
    End Sub

    Sub Main()
        Dim sb1 As StringBuilder = New StringBuilder("StringOne")
        HyphenatedConcat(sb1, "StringTwo")
        Console.WriteLine(sb1)
    End Sub
End Module

Esta versão do programa gerenciar as mesmas saída que a primeira versão, porque a função de HyphenatedConcat alterou o valor (estado) do primeiro parâmetro chamar a função de membro de Append . Observe que essa mudança ocorre independentemente do fato de que HyphenatedConcat usa passar o parâmetro de atendimento-por- valor.

Importante

Para tipos de referência, se você passa um parâmetro por valor, ele resulta em uma cópia de referência a um objeto que está sendo passado. Esta cópia ainda está associada com os mesmos dados de instância que a referência original (até que a variável de referência é atribuído a um novo objeto). A chamada por referência não necessariamente é obrigatória para uma função modificar um parâmetro.

Exemplo: implementar uma função pura

Esta próxima versão do programa mostra como implementar a função HyphenatedConcat como uma função pura.

class Program
{
    public static string HyphenatedConcat(string s, string appendStr)
    {
        return (s + '-' + appendStr);
    }

    public static void Main(string[] args)
    {
        string s1 = "StringOne";
        string s2 = HyphenatedConcat(s1, "StringTwo");
        Console.WriteLine(s2);
    }
}
Module Module1
    Public Function HyphenatedConcat(ByVal s As String, ByVal appendStr As String) As String
        Return (s & "-" & appendStr)
    End Function

    Sub Main()
        Dim s1 As String = "StringOne"
        Dim s2 As String = HyphenatedConcat(s1, "StringTwo")
        Console.WriteLine(s2)
    End Sub
End Module

Além disso, esta versão gerencia a mesma linha de saída: StringOne-StringTwo. Observe que para manter o valor concatenado, ele é armazenado em s2variável intermediária.

Uma abordagem que pode ser muito útil é escrever as funções que são localmente impuros (isto é, declare e alteram variáveis locais) mas é global pura. Tais funções têm muitas das características desejáveis de composability, mas impedem alguns de linguagem e mais complicados de programação, como ter que usar a recursão quando um loop simples realizaria a mesma coisa.

Operadores de consulta padrão

Uma característica importante dos operadores de consulta padrão é que são implementados como funções puras.

Para mais informações, confira Visão geral de operadores de consulta padrão (C#) e Visão geral de operadores de consulta padrão (Visual Basic).

Confira também