C# 4.0 – Named och Optional Parameters

När man utvecklar klasser som innehåller många överlagrade metoder så händer det ofta att man först har en “huvudmetod” som innehåller alla parametrar, och sedan ett par överlagrade metoder med ett visst antal parametrar, vilka sedan anropar huvudmetoden.

Ett exempel på det är:

using System;
 
namespace OptionalNamedParameters
{
    public class OldParameters
    {
        public static string HelloWorld(string Word1, string Word2, string Word3)
        {
            return String.Format("{0} {1} {2}", Word1, Word2, Word3);
        }
 
        public static string HelloWorld(string Word1, string Word2)
        {
            return HelloWorld(Word1, Word2, "Tom");
        }
 
        public static string HelloWorld(string Word1)
        {
            return HelloWorld(Word1, "Tom", "Tom");
        }
    }
}

Här har vi tre överlagrade metoder. Den första har tre parametrar och returnerar alla strängar hopsatta med mellanslag som separator. De övriga två anropar den första, men med värdet ”Tom” för den eller de parametrar som inte används.

Om vi sedan kör den här koden:

Console.WriteLine(OldParameters.HelloWorld("Hello,", "world", "!"));
Console.WriteLine(OldParameters.HelloWorld("Hello,", "world"));
Console.WriteLine(OldParameters.HelloWorld("Hello,"));

Så får vi:

Hello, world !
Hello, world Tom
Hello, Tom Tom

Problemet här är att vi väldigt ofta behöver skapa metoder likt dessa för att ändå bara anropa en av dem, vilket gör att vi får fler metoder som inte tillför något.

En lösning på detta har sedan länge funnits i Visual Basic, nämligen optional parameters. I och med .NET 4.0 så kan vi använda detta även med C#. Vi kan med optional parameters förkorta ned detta till enbart en enda metod, men som har standardvärden för de parametrar som inte behöver anges.

För att göra detta så lägger vi till =”Standardvärde” efter parametern.

using System;
 
namespace OptionalNamedParameters
{
    public class NewParameters
    {
        public static string HelloWorld(string Word1, string Word2="Tom", string Word3="Tom")
        {
            return String.Format("{0} {1} {2}", Word1, Word2, Word3);
        }
    }
}

Här har vi först en obligatorisk parameter (Word1), och sedan två valfria med standardvärden satta. Genom att lägga till ett standardvärde så blir parametern automatiskt valfri att använda. Om parametern inte skickas in så används standardvärdet.

För att använda detta så kan vi köra samma kod som innan (jag har dock ett annat klassnamn i exemplet):

Console.WriteLine(NewParameters.HelloWorld("Hello,", "world", "!"));
Console.WriteLine(NewParameters.HelloWorld("Hello,", "world"));
Console.WriteLine(NewParameters.HelloWorld("Hello,"));

Detta ger samma resultat som innan:

Hello world !
Hello world Tom
Hello Tom Tom

Genom att sätta standardvärden på de två valfria parametrarna så har vi gått från tre metoder till en enda. Det här gör koden mer lättläst och lättare att underhålla. Vid de fall där man har många olika varianter så kan det göra stor skillnad.

Problemet nu uppstår om vi vill använda specifika parametrar här, och inte alla i ordning. Det kan vi lösa med en annan nyhet – named parameters.

För att använda named parameters så anger vi vid anropet namnet på parametern och dess värde separerat med kolon. Parametrarna behöver inte anges i rätt ordning, utan vi kan blanda som vi vill.

Om vi tar den nya klassen med bara en metod så kan vi enkelt använda detta:

Console.WriteLine(NewParameters.HelloWorld(Word3: "!", Word2: "world", Word1: "Hello"));
Console.WriteLine(NewParameters.HelloWorld(Word2: "world", Word1: "Hello"));
Console.WriteLine(NewParameters.HelloWorld(Word1: "Hello"));

Här anropar vi parametrarna i bakvänd ordning. Vi anropar dock exakt samma parametrar med samma värden som innan, så om vi kör det så får vi återigen:

Hello world !
Hello world Tom
Hello Tom Tom

Det är även möjligt att ange parametrarna som vanligt, samtidigt som vi använder namngivna parametrar för de resterande parametrarna.

Ett exempel på det är:

Console.WriteLine(NewParameters.HelloWorld("Hello", Word3: "!", Word2: "world"));
Console.WriteLine(NewParameters.HelloWorld("Hello", Word2: "world"));

I det första exemplet så anger vi “Hello” som den första parametern, “!” som den tredje parametern (dock tvåa i ordningen), samt ”world” som den andra parametern (sist i ordningen). Vi kan inte flytta den första parametern här, utan de som inte är namngivna måste vi ange innan de som är namngivna.

Tack vare stödet för named och optional parameters i C# 4.0 så kan vi förminska antalet rader kod och samtidigt få den mer läsvänlig.

No Comments