Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Proposal: Default Parameters/Named Parameters

4 views
Skip to first unread message

cody

unread,
Feb 2, 2005, 1:40:44 PM2/2/05
to
Why doesn't C# allow default parameters for methods?
An argument against I hear often is that the default parameters would have
to be hardbaken into the assembly, but why? The Jit can take care of this,
if the code is jitted the
"push xyz" instructions of the actual default values can be inserted.

To make things simpler and better readable I'd make all default parameters
named parameters so that you can decide for yourself why one to pass and
which not, rather than relying on massively overlaoded methods which
hopefully provide the best overload for you, for example the Image.DrawImage
method has 20 overloads.

I propose a syntax like the following:

public void Open(string path, AccessMode mode = AccessMode.Read, int
bufferSize=1024)
{
// ...
}

As you can see, path is a regular parameter which cannot be omitted, whereas
Mode and BufferSize provide default values an can be omitted when calling
the method.
Named parameters can only be declare behind all regular parameters and if
you have params parameters (variable parameterlist) is must be declared at
the end of the parameterlist. Although you can omit the named parameters if
you pass them they should appear in the same order as they were declared for
better readability.

You could call the example method like the following:

Open("text.txt", @mode=AccessMode.Write, @bufferSize=512);
Open("text.txt", @bufferSize=512);
Open("text.txt", @mode=AccessMode.Write);
Open("text.txt");

Note that an @ sign has to appear before all named parameter so that you
have no naming conflicts with other variables in the callers context.

Additionally there can not be more that one method with the same name and
the same regular parameters to avoid ambigiuty, so:

Foo(int i, string a="");
Foo(int i, double f=1.0f);

Would not be allowed because the call Foo(100) could not be resolved.

What do you think about that? Would it even be possible to do that in the
CLR or would there have be so huge changes that it can't be done in the
future?


Bruce Wood

unread,
Feb 2, 2005, 2:22:29 PM2/2/05
to
Anders Hejlsberg touched on this during his (very interesting)
whiteboard talk:

http://msdn.microsoft.com/msdntv/episode.aspx?xml=episodes/en/20040624csharpah/manifest.xml

Basically, there are several ways to implement default arguments.

The first is to have the compiler build the defaults into the method
call on the caller's side. Essentially the called method would receive
all of its parameter arguments every time and not have to worry about
missing arguments, because the caller would take care of filling in the
blank. Hejlsberg's objection to this is that it would involve compiling
the defaults into the caller, which would break all of your callers if
you ever changed the defaults.

However, you're suggesting doing it during the JIT phase, which would
remove that objection, but require changes to the IL. An interesting
idea.

The other possibility is to have the called method handle defaulting,
but this would come with a mondo speed penalty, as I think Hejlsberg
points out.

Personally, the only place I've found that really could use optional
parameters is when writing constructors. Most other methods don't
experience the kind of massive overloading that constructors do, and
the only part of writing constructor overloads that I hate is having to
copy (and maintain) the documentation on every overload.

Someone also mentions this to Hejlsberg as a compromise: allowing
sharing of XML documentation between overloaded methods / constructors.
That would make me happy enough, without changing the IL, the JITter,
and the definition of what a C# method signature looks like.

Bob Powell [MVP]

unread,
Feb 2, 2005, 3:37:51 PM2/2/05
to
Default parameters are not needed when overloading can do the job for you.

The parameter lists scan from left to right anyway so all you have to do is
overload the function once for each extra parameter in the list.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

"cody" <deutr...@gmx.de> wrote in message
news:uFmfeaVC...@TK2MSFTNGP14.phx.gbl...

Bruce Wood

unread,
Feb 2, 2005, 3:50:51 PM2/2/05
to
There is one situation in which _named_ parameters, as outlined by
cody, would be helpful, and that is when you have what really ought to
be two different overloads that take the same parameter types,
something like

public Page (int width, int height)

public Page (int width)

now, if you want another constructor overload for Page that creates a
Page with a default width and a given height, you're stuck.

However, I'm fairly certain that it's not worth reworking the C#
language and the IL in order to handle this one, rare case.

Bob Powell [MVP]

unread,
Feb 2, 2005, 4:08:37 PM2/2/05
to
It strikes me that this can be done with attributes. I'll have to think
about it.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

"Bruce Wood" <bruc...@canada.com> wrote in message
news:1107377451.7...@z14g2000cwz.googlegroups.com...

cody

unread,
Feb 2, 2005, 7:28:10 PM2/2/05
to
Please tell me if you should have a new idea!

"Bob Powell [MVP]" <bob@_spamkiller_bobpowell.net> schrieb im Newsbeitrag
news:uVWUYtWC...@TK2MSFTNGP12.phx.gbl...

cody

unread,
Feb 2, 2005, 7:43:25 PM2/2/05
to
> Personally, the only place I've found that really could use optional
> parameters is when writing constructors. Most other methods don't
> experience the kind of massive overloading that constructors do, and
> the only part of writing constructor overloads that I hate is having to
> copy (and maintain) the documentation on every overload.

There are a lot of methods that take a lot for than 5 arguments and have
multiple overloads like the framework class Image which method DrawImage has
20 overloads!

I think this heavy overlading makes the code less readable and unnessaccary
bloated.
So if you have just 5 overloads you have to write at least 5*5 lines of code
and this is without documentation. You often do not see which overloaded
method calls which and you sometimes end up with an endless recursion. You
have also take care that the parameters ar in the same order in each method
to provide good readability.
Additionally if you do not do it clean and put additional code in the
overadloaded methods beside the call of the "main worker method" end up with
very messy code like that:

Foo(double d, string s, int i, bool b)
{
// dostuff
}

Foo(double d, string s, int i)
{
Foo(d, s, 0, false);
// do some stuff here
}

Foo()
{
Foo(0, "", 0, false);
// do some stuff here
}

Foo(double d)
{
Foo(0, "", 0, false);
// do some stuff here
}

Foo(int i)
{
Foo(0, "", i, false);
// do some stuff here
}

Foo(double d, string s)
{
Foo(d, s, i, false);
// do some stuff here
}

At the end, you have a huge piece a crap in you texteditor where you just
would have needed JUST ONE SIMPLE METHOD.


Bruce Wood

unread,
Feb 3, 2005, 2:04:41 AM2/3/05
to
Do I need to point out that if each overload has some extra "do some
stuff here" code that isn't in the "master method" then you couldn't
code it any better using default arguments? :)

Really, for my money the only annoying thing about having to use
overloads is copying the documentation over and over again. Fix that
problem and I would be quite happy with the status quo.

Rick Byers [MSFT]

unread,
Feb 7, 2005, 4:12:10 PM2/7/05
to
Note that emitting default values at JIT time wouldn't cover the important
case where the caller is an ngen'd image. It's not clear to me off hand
how you could support that scenario in an efficient manor.

I'd personally love to see something like this, but only if it could be
efficiently implemented without sacrificing the simplicity and elegance of
C#. The complexity of overload resolution in C++ (and resulting costs) was
probably a driving factor in the C# design. I know Anders and his team
have spent some effort trying to come up with an acceptable solution here
(and they would have asked for CLR support if they thought it would help).

Regardless, feel free to add your comments and vote to this topic in the
MSDN product feedback center:
http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=8
2bdeff1-0588-4c9d-9172-7c4f1eab0f8c

We take that feedback very seriously, and try to allocate our resources in
proportion to the demand from the community.

Rick

--------
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
> From: "Bruce Wood" <bruc...@canada.com>
> Newsgroups:
microsoft.public.dotnet.framework.clr,microsoft.public.dotnet.languages.csha
rp
> Subject: Re: Proposal: Default Parameters/Named Parameters
> Date: 2 Feb 2005 11:22:29 -0800

cody

unread,
Feb 7, 2005, 5:40:06 PM2/7/05
to
Even if using an NGened image, it would certainly be possible to "rejit"
some portions of the code.

But if you ask me NGen as a whole goes completely against the spirit of a
virtual machine and defeats all of its advantages like dynamically
optimizing and creating code and so on.
Couldn't we simply say that from the version on where named parametern are
supported NGen is no longer supported?

NGen serves no other purpose than having precompiled code, you could have
the same effect if you would enable the CLR to cache every assembly which is
in the GAC as native image. And only if a assembly changes (which means
there could be a new default value of a named parameter) all depending
assemblies have to be re-precompiled by the CLR on demand.

""Rick Byers [MSFT]"" <rby...@online.microsoft.com> schrieb im Newsbeitrag
news:kMFKymVD...@cpmsftngxa10.phx.gbl...

cody

unread,
Feb 7, 2005, 6:42:52 PM2/7/05
to
> Note that emitting default values at JIT time wouldn't cover the important
> case where the caller is an ngen'd image. It's not clear to me off hand
> how you could support that scenario in an efficient manor.

Maybe I understood you wrong. In case of an NGened image we simple pass
*all* of the parameters to the method in the order they are declared in it.
At the end there is no performance penalty because when programming with the
main method pattern to fake optional parameters using heavy overloading we
also have to call the main method with *all* parameters.

What would happen if I change the default value? In that case the method
signature has changed in which case the NGened images are incompatible and
have to be recompiled anyway.

Another great idea is that we use the same syntax I proposed, but we let the
c# compiler emit the various overloaded methods so they do not clutter our
sourcecode anymore but instead are located in the assembly. This way we stay
very compatible because we do not have to modify the CLR but only the c#
compiler and we dealt gracefully with modifying default values because they
are stored in the assembly.
But this approach has its drawbacks - we can only omit the parameters from
the end of the parameter list and cannot simply leave some arguments out.
But I think this would be very enough for the most common uses.

Rick Byers [MSFT]

unread,
Feb 8, 2005, 3:06:26 PM2/8/05
to
Of course, you're right - the requirement to re ngen an image when any of
its referenced assemblies changes means the burned-in defaults would be
updated. I don't know what I was thinking - thanks for keeping me honest
<grin>. Note, by the way, that in his whiteboard talk Anders indicated that
the burn-in problem may not be that important.

Having the compiler emit a series of overloads also sounds like a decent
option (although it does still increase the complexity and potential for
error in overload resolution). However, during his whiteboard talk,
Anders' mentioned the possibility of object initialization syntax that may
be an even better option. Basically, instead of writing default arguments
like this:

public MyClass( int arg1=0, string arg2="foo", object arg3=null )

you would use properties like this:

public MyClass()
{
Arg1=0;
Arg2="foo";
Arg3=null;
}
public int Arg1 { get {...} set {...} }
public string Arg2 { get { ... } set {...} }
public object Arg3 { get {...} set {...} }

And then you could easy create an instance with a statement like
new MyClass{ Arg1=4, Arg3=o }

If you didn't want to expose your constructor parameters as properties
(i.e. you didn't want to let people change them after construction), you
could just wrap them all up in a struct and use the object construction
syntax to create a set of values that you pass to the constructor. This
would also be usefull for other (non-constructor) methods with long
argument lists.

I like this a lot (especially since it's avoids the overload resolution
complexity in languages like C++, and doesn't require any CLR support).
There is something about optionally named arguments I've always found
appealing, and Anders' suggestion has that same appeal. Hopefully we'll
see something like this in C# 3. Of course, I have no idea how likely this
would be. If you like it, you should vote on it in the product feedback
center
(http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=
6efe5713-405f-4808-9449-9caa0f116d6f).

Rick

--------
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------

> From: "cody" <deutr...@gmx.de>


> Subject: Re: Proposal: Default Parameters/Named Parameters

> Date: Tue, 8 Feb 2005 00:42:52 +0100

cody

unread,
Feb 8, 2005, 4:44:22 PM2/8/05
to
> However, during his whiteboard talk,
> Anders' mentioned the possibility of object initialization syntax that may
> be an even better option. Basically, instead of writing default arguments
> like this:
>
> public MyClass( int arg1=0, string arg2="foo", object arg3=null )
>
> you would use properties like this:
>
> public MyClass()
> {
> Arg1=0;
> Arg2="foo";
> Arg3=null;
> }
> public int Arg1 { get {...} set {...} }
> public string Arg2 { get { ... } set {...} }
> public object Arg3 { get {...} set {...} }
>
> And then you could easy create an instance with a statement like
> new MyClass{ Arg1=4, Arg3=o }

I do not like that proposal. I do not see any benefit of using

MyClass obj = new MyClass
{
Arg1=4,
Arg2=o
Arg3=o
}

over

MyClass obj = new MyClass();
obj.Arg1=4;
obj.Arg1=o;
obj.Arg3=o;

I find the first harder to read and it suggests that you cannot alter the
values
afterwards, additionally it doesn't look consistent to the rest of c#, it
has
something from the "with" statement which also does not fit into the
language
which is also anders' opinion.

And it can only be used with ctors which introduces additionally
inconsistency,
it is not only that I do not like it, I hate it!

<endofcomments>

Carl Shapiro

unread,
Feb 13, 2005, 3:49:58 AM2/13/05
to
rby...@online.microsoft.com ("Rick Byers [MSFT]") writes:

> Note that emitting default values at JIT time wouldn't cover the important
> case where the caller is an ngen'd image. It's not clear to me off hand
> how you could support that scenario in an efficient manor.

Efficient compilation of function calls with optional named parameters
is a problem that has been studied by Lisp implementors. One approach
used by aggressively-optimizing Common Lisp compilers that may be
useful in this situation is to provide multiple external entry points
for functions which take optional named parameters. One entry point
would be for the fast case: a function call with all parameters
supplied. Entering a function through the fast entry point should be
no more expensive than calling a method with only mandatory positional
arguments. Another entry point, the default entry point, would be for
function calls where unsupplied arguments would be filled in. (After
all values are moved into place the function would fall through or
jump to the fast entry point.) In this case, the call should be no
more expensive than a function which tests and assigns default values
to unsupplied optional parameters. Other entry points could be made
available for various combinations of supplied and unsupplied
parameters, although this could easily become unmanageable. If space
is of concern, the entire defaulting operation could be performed in a
small out-of-line subroutine.

Actually, with the params keyword, you can implement named optional
parameters in a simpleminded way: pass pairs of keywords and values in
the params vector.

func(param1, param2, "keyword1", value1, "keyword2", value2)

I am surprised nobody has suggested something like this. Granted, the
syntax is just awful; it's not immediately clear what the programmer
is trying to say. On the other hand, it is representative of what
could be happening under the hood. If we could cheat on the syntax
for argument lists, and rather than using random strings, we had a way
to ask for self-evaluating constant strings, this expression could be
made less of an eye-sore

func(param1, param2, keyword1: value1, keyword2: value2)

A small out-of-line subroutine could be invoked to scan the params
vector and move keyword-values into predetermined local variables.

Imagine if the compiler could do that for you!

cody

unread,
Feb 14, 2005, 11:01:18 AM2/14/05
to
> It strikes me that this can be done with attributes. I'll have to think
> about it.

Iam just curious if you've got new ideas about this topic :)

Rick Byers [MSFT]

unread,
Feb 14, 2005, 1:43:07 PM2/14/05
to
You make some good points, and I agree the benefit isn't clear but I still
think the proposal has some merrit. I don't envy the C# team's job of
trying to satisfy as many people as possible without upsetting too many
<grin> when it's such a religious issue. The art of language design is
sufficiently subjective and debatable, that at some point you just need an
expert (like Anders) to make a judgement call (which is precisely what has
been done to date with default parameters).

Regardless, feel free to give the C# team your feedback (either in the
product feedback center, the C# language discussion group[1], or the
languages.csharp newsgroup). Debating this issue on the CLR group probably
isn't going to get us anywhere since it's utlimately a language issue, even
if the CLR ends up providing support for the implementation.

Rick

[1]
http://www.gotdotnet.com/Community/MessageBoard/MessageBoard.aspx?ID=5627

--------
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
> From: "cody" <deutr...@gmx.de>
> Subject: Re: Proposal: Default Parameters/Named Parameters

> Date: Tue, 8 Feb 2005 22:44:22 +0100

Rick Byers [MSFT]

unread,
Feb 14, 2005, 1:49:47 PM2/14/05
to
Thanks for your input Carl. I agree that using multiple entry points is
probably the best way to prevent burn-in without getting any support from
the CLR.

For your params-based named parameters proposals, keep in mind that most C#
users may not be willing to give up strong typing for a relatively minor
cosmetic feature like named/default parameters (which makes it
significantly different from the Lisp environment where you've got a lot
more freedom in this respect). Of course, named parameters could be added
to the language in a simple strongly-typed way if there was sufficient
demand.

Rick

--------
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------

> From: Carl Shapiro <cshapi...@panix.com>
> Newsgroups: microsoft.public.dotnet.framework.clr


> Subject: Re: Proposal: Default Parameters/Named Parameters

> Date: 13 Feb 2005 03:49:58 -0500

cody

unread,
Feb 15, 2005, 3:43:05 AM2/15/05
to
> You make some good points, and I agree the benefit isn't clear but I still
> think the proposal has some merrit.

The Property calling syntax in ctors enables you to initialize an object and
call properties of it in array initializers:

object[] array = { new MyClass{Prop1=val1,Prop2=val2} };

But when would somebody actually need that?

0 new messages