Dela via


Omstrukturera till rena funktioner (LINQ till XML)

En viktig aspekt av rena funktionella transformeringar är att lära sig att omstrukturera kod med hjälp av rena funktioner.

Kommentar

Den gemensamma nomenklaturen i funktionell programmering är att du omstrukturerar program med hjälp av rena funktioner. I Visual Basic och C++, överensstämmer detta med användningen av funktioner på respektive språk. I C#kallas dock funktioner för metoder. I den här diskussionen implementeras en ren funktion som en metod i C#.

Som tidigare nämnts i det här avsnittet har en ren funktion två användbara egenskaper:

  • Det har inga biverkningar. Funktionen ändrar inga variabler eller data av någon typ utanför funktionen.
  • Det är konsekvent. Med samma uppsättning indata returnerar den alltid samma utdatavärde.

Ett sätt att övergå till funktionell programmering är att omstrukturera befintlig kod för att eliminera onödiga biverkningar och externa beroenden. På så sätt kan du skapa rena funktionsversioner av befintlig kod.

I den här artikeln beskrivs vad en ren funktion är och vad den inte är. Självstudiekursen : Manipulera innehåll i ett WordprocessingML-dokument visar hur du manipulerar ett WordprocessingML-dokument och innehåller två exempel på hur du omstrukturerar med hjälp av en ren funktion.

I följande exempel kontrasterar två icke-rena funktioner och en ren funktion.

Exempel: Implementera en icke-ren funktion som ändrar en statisk klassmedlem

I följande kod HyphenatedConcat är funktionen inte en ren funktion eftersom den ändrar den aMember statiska klassmedlemmen:

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

Det här exemplet genererar följande utdata:

StringOne-StringTwo

Observera att det är irrelevant om data som ändras har eller private har public åtkomst eller är medlemstatic, shared medlem eller instansmedlem. En ren funktion ändrar inte några data utanför funktionen.

Exempel: Implementera en icke-ren funktion som ändrar en parameter

Dessutom är följande version av samma funktion inte ren eftersom den ändrar innehållet i parametern . 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

Den här versionen av programmet genererar samma utdata som den första versionen, eftersom HyphenatedConcat funktionen har ändrat värdet (tillståndet) för den första parametern genom att Append anropa medlemsfunktionen. Observera att den här ändringen sker trots att HyphenatedConcat parametern call-by-value används.

Viktigt!

Om du skickar en parameter efter värde för referenstyper resulterar det i en kopia av referensen till ett objekt som skickas. Den här kopian är fortfarande associerad med samma instansdata som den ursprungliga referensen (tills referensvariabeln har tilldelats till ett nytt objekt). Anrop efter referens krävs inte nödvändigtvis för att en funktion ska kunna ändra en parameter.

Exempel: Implementera en ren funktion

Nästa version av programmet visar hur du HyphenatedConcat implementerar funktionen som en ren funktion.

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

Återigen genererar den här versionen samma utdatarad: StringOne-StringTwo. Observera att för att behålla det sammanfogade värdet lagras det i den mellanliggande variabeln s2.

En metod som kan vara mycket användbar är att skriva funktioner som är lokalt orena (det vill säga deklarerar och ändrar lokala variabler) men som är globalt rena. Sådana funktioner har många av de önskvärda sammansättningsegenskaperna, men undvik några av de mer invecklade funktionella programmerings-idiomerna, till exempel att behöva använda rekursion när en enkel loop skulle åstadkomma samma sak.

Vanliga frågeoperatorer

En viktig egenskap hos standardfrågeoperatorerna är att de implementeras som rena funktioner.

Mer information finns i Översikt över vanliga frågeoperatorer (C#) och Översikt över standardfrågasoperatorer (Visual Basic).

Se även