.NET features: Optional Parameters

Door Luuk1983 op maandag 20 juni 2011 08:36 - Reacties (23)
Categorie: Programmeren, Views: 2.548

Als .NET-programmeur merk ik regelmatig dat andere programmeurs niet op de hoogte zijn van sommige handige en slimme features in het .NET framework die het programmeren een stuk makkelijker kunnen maken. Soms zijn deze features verstopt, of soms zijn ze pas nieuw, maar handig zijn ze altijd. Dit is deel 1 van een serie met kleine voorbeelden van features die je als .NET-programmeur (met name in C#) mogelijk nog niet kent. Deze keer: optional parameters in C#.

Optional Parameters zijn nieuw in .NET 4.0 voor C# en kunnen gebruikt worden om één functie met meerdere signatures te maken in plaats van meerdere overloaded functies. Deze functionaliteit is al langer beschikbaar in VB.NET. Een simpel voorbeeld van een paar overloaded functies:


C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void DoSomething()
{
    DoSomething(false, false);
}

public void DoSomething(bool bool1)
{
    DoSomething(bool1, false);
}

public void DoSomething(bool bool1, bool bool2)
{
    //Here code that does something
}



In .NET 4.0 kan dit samengevoegd worden tot één functie door middel van optional parameters. Je geeft dan aan welke properties optioneel zijn, waarna je ze niet perse hoeft in te vullen. Let wel op dat de optionele parameters altijd achteraan moeten komen te staan.

Je maakt parameters optioneel door ze een default waarde te geven:


C#:
1
2
3
4
public void DoSomething(bool bool1 = false, bool bool2 = false)
{
    //Here code that does something
}



Op dit moment zijn de volgende aanroepen naar bovenstaande functie geldig:


C#:
1
2
3
DoSomething();
DoSomething(false);
DoSomething(false,false);



Zoals je ziet zijn de drie overloaded functies aan het begin van deze blog nu vervangen door één functie met optionele parameters. Er is echter ook nog een belangrijk voordeel aan het gebruik van optional parameters: je hoeft niet perse alle optionele parameters in te vullen. Zo kan je in bovenstaand voorbeeld er ook voor kiezen om alleen de tweede parameter in te vullen en de eerste de default waarde te laten behouden:


C#:
1
DoSomething(bool2: true);



bool1 zal in dit geval zijn default waarde van false behouden en wordt alleen bool2 expliciet ingevuld.

Ik hoop dat jullie er wat aan hebben, of mochten er mensen zijn die nog wat aanvullingen hebben, dan hoor ik het graag.

Volgende: .NET Features: auto properties 06-'11 .NET Features: auto properties
Volgende: Kopie van een kopie... 11-'10 Kopie van een kopie...

Reacties


Door Tweakers user Wallie, maandag 20 juni 2011 08:57

Weet je misschien ook wat het verschil is met de optionele parameters zoals ze al jaren in VB(.net) bestaan?

Ik vermoed dat dit er in is gekomen om tegen de office interface aan te praten, welke nogal veel optionele parameters kent, en je alleen hierom al vb.net wilde gebruiken als je hiertegen moest programmeren.

[Reactie gewijzigd op maandag 20 juni 2011 08:57]


Door Tweakers user Rhapsody, maandag 20 juni 2011 09:11

Volgens mij is dit nieuw in C# en niet in .NET 4 algemeen. in VB.net kon dit inderdaad al langer (zoals Wallie geschreven heeft)

Wel een leuke en informatieve blogpost, hopelijk volgen er nog meer :-)

[Reactie gewijzigd op maandag 20 juni 2011 09:11]


Door Tweakers user Luuk1983, maandag 20 juni 2011 09:20

Ik heb de tekst aangepast dat het over C# gaat en dat VB.NET deze feature al langer heeft.

Door Tweakers user CodeCaster, maandag 20 juni 2011 09:24

DoSomething is natuurlijk een heerlijke abstracte methode om het principe uit te leggen, maar ik ben nog nooit een toepassing toegekomen van optional en/of named parameters, die niet op een andere manier opgelost had kunnen worden.

Heb je wellicht ook een concreet voorbeeld? :)

[Reactie gewijzigd op maandag 20 juni 2011 09:34]


Door Tweakers user Punkie, maandag 20 juni 2011 09:25

In de rest van de wereld staat dit bekend als default parameters. Waar ik me over verbaas is dat dit nu pas in C# wordt geïntroduceerd, zeker omdat iedereen dit al lange tijd gewoon is in c++.

Door Tweakers user Snake, maandag 20 juni 2011 09:36

Interessant om te weten: Default parameters moeten constanten zijn. Gelijk je een const declareert, je kan dus niet een default object meegeven, dan moet je gaan werken met ordinaire overloads :)

Door Tweakers user IStealYourGun, maandag 20 juni 2011 09:56

Optional parameters kende ik nog uit de wereld van PHP. Onder vb.net ging er echter een nieuwe wereld open met overloading. Mijn oud leraar (die ook van beroep programmeur is) gaf in elk geval de voorkeur vaan overloading en ik persoonlijk ook.

Door Tweakers user Luuk1983, maandag 20 juni 2011 10:13

@CodeCaster:
Ik gebruik regelmatig het CMS Umbraco en heb zelf een DLL gemaakt met extensions en ondersteunende functies van dingen die ik vaak gebruik. Door middel van optionele parameters kan je aangeven hoe er met fouten omgegaan wordt. Hierdoor heb je drie mogelijkheden: fouten niet afvangen, null retourneren in het geval van een fout, of een default object teruggeven als het fout gaat.

@Snake: eh...?

@IStealYourGun:
Dat is een keuze die je als programmeur uiteraard zelf mag maken. Ik heb liever zo kort mogelijke code. Als de overloaded functies, zoals in mijn voorbeeld, niks anders doen dan de andere overloaded functie aanroepen, dan zie ik de meerwaarde niet in om geen optional parameters te gebruiken. Doe je echter in de overloaded functies eerst vanalles voordat je de andere overloaded functie aanroept, dan is het weer een ander verhaal.

Door Tweakers user ZpAz, maandag 20 juni 2011 10:46

Volgens mij hebben ze dit van PHP afgekeken (A) Ik wist altijd al wel dat PHP een inspiratie was voor ons allen ;)

Door Tweakers user Snake, maandag 20 juni 2011 10:48

@Luuk1983:


C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Foo { /* ... */ } 

// dit gaat niet
class Bar()
{
    void FooBar(Foo foo = new Foo() { /* ... */ }) { /* ... */ }
}

// dit gaat wel:
class Bar()
{
    void FooBar() 
    {  
         FooBar(new Foo() { /* ... */ });
    }    
    void FooBar(Foo foo) { /* ... */ }
}


Door Tweakers user SKiLLa, maandag 20 juni 2011 11:10

ZpAz schreef op maandag 20 juni 2011 @ 10:46:
Volgens mij hebben ze dit van PHP afgekeken (A) Ik wist altijd al wel dat PHP een inspiratie was voor ons allen ;)
N00b :P

Door Tweakers user Luuk1983, maandag 20 juni 2011 11:16

@Snake:
Ah, op die manier. Duidelijk :)

Door Tweakers user Forsith, maandag 20 juni 2011 12:53

Zoals hierboven al vermeldt, zit dit al sinds jaar en dag in C++. MSDN definieert dit als "Default Arguments". Het is denk ik dus best gek dat het lange tijd niet in C# heeft gezeten (in Java kan het zover ik weet ook niet), aangezien het een handige functie is die sommige dingen net wat overzichtelijker kan maken.

Overigens, dit was niet als belediging bedoeld, maar iets wat mij opviel :-)

[Reactie gewijzigd op maandag 20 juni 2011 12:54]


Door Tweakers user Sebazzz, maandag 20 juni 2011 13:52

Microsoft Code Analysic (FxCop) raadt overigens wel aan om behalve de optional parameters altijd nog overloads aan te maken (geloof ik).

Door Tweakers user Jaap-Jan, maandag 20 juni 2011 14:22

CodeCaster schreef op maandag 20 juni 2011 @ 09:24:
DoSomething is natuurlijk een heerlijke abstracte methode om het principe uit te leggen, maar ik ben nog nooit een toepassing toegekomen van optional en/of named parameters, die niet op een andere manier opgelost had kunnen worden.

Heb je wellicht ook een concreet voorbeeld? :)
Het scheelt een hoop typwerk voor functies met veel parameters. Anders gezegd: goede 'syntactic sugar'. :)

Door Tweakers user riezebosch, maandag 20 juni 2011 14:23

Het probleem zit erin dat de waarde van een optional paramter aan de aanroepende kant ingecompileerd wordt. Wanneer je aan een public method in een library een andere default waarde geeft voor de optional parameter zal dit bij afhankelijke libraries pas doorgevoerd worden als deze ook opnieuw gecompileerd worden. Daarom klaagt FxCop daar over bij public methods van public classes.

Door Tweakers user kipusoep, maandag 20 juni 2011 14:37

Luuk1983 schreef op maandag 20 juni 2011 @ 10:13:
@CodeCaster:
Ik gebruik regelmatig het CMS Umbraco [...]
Waar was je dan afgelopen week met CG11? :P

Door Tweakers user berendhaan, maandag 20 juni 2011 15:34

Let wel dat er wat corner cases zijn met het gebruik van optional parameters. Vooral het gebruik ervan in libraries kunnen voor rare problemen zorgen.

Zie ook: http://blogs.msdn.com/b/e...orner-cases-part-one.aspx

Door Tweakers user Voxyn, maandag 20 juni 2011 16:13

_/-\o_ Ts gaat mij heel veel tijd besparen :P

Door Tweakers user FlowinG, dinsdag 21 juni 2011 09:39

Het is niet nieuw voor .NET 4, maar wel voor Visual Studio 2010: het werkt namelijk ook met oudere .NET zolang het maar in VS2010 gemaakt is.

Door Tweakers user Luuk1983, dinsdag 21 juni 2011 10:20

@FlowinG:
Het lijkt me dat de compiler het vooral moet snappen. Ik weet dat je in Visual Studio 2010 andere target frameworks kan opgeven, maar ik denk dat ze wel door de laatste versie van de compiler gegooid worden. Of je dat nou de .NET4.0 compiler moet noemen of niet weet ik niet, maar het is in ieder geval de Visual Studio 2010 compiler zoals je aangeeft.

Door Tweakers user kipusoep, dinsdag 21 juni 2011 15:14

berendhaan schreef op maandag 20 juni 2011 @ 15:34:
Let wel dat er wat corner cases zijn met het gebruik van optional parameters. Vooral het gebruik ervan in libraries kunnen voor rare problemen zorgen.

Zie ook: http://blogs.msdn.com/b/e...orner-cases-part-one.aspx
Heuy B!!!

Door Tweakers user Punkie, dinsdag 21 juni 2011 20:01

berendhaan schreef op maandag 20 juni 2011 @ 15:34:
Let wel dat er wat corner cases zijn met het gebruik van optional parameters. Vooral het gebruik ervan in libraries kunnen voor rare problemen zorgen.

Zie ook: http://blogs.msdn.com/b/e...orner-cases-part-one.aspx
Corner cases had je trouwens in C++ ook. Als je de functie 2x declareert met verschillende defaults dan gaat dit wel vlot door de compiler (in 2 verschillende compilation units) maar als dev is het moeilijk de 2 gevallen uit elkaar te houden.

Reactie formulier
(verplicht)
(verplicht, maar wordt niet getoond)
(optioneel)