C# 4.0, Optional Parameters and Params Do Not Work Together

C# 4.0, optional parameters and params do not work together

Your only option right now is to overload the TestOptional (as you had to do before C# 4). Not preferred, but it cleans up the code at the point of usage.

public static void TestOptional(string A, params string[] C)
{
TestOptional(A, 0, C);
}

public static void TestOptional(string A, int B, params string[] C)
{
Console.WriteLine(A);
Console.WriteLine(B);
Console.WriteLine(C.Count());
}

Optional argument followed by Params

I can find three ways of calling the method without specifying a value for the first parameter:

using System;

class Test
{
static void PrintValues(string title = "Default",
params int[] values)
{
Console.WriteLine("{0}: {1}", title,
string.Join(", ", values));
}

static void Main()
{
// Explicitly specify the argument name and build the array
PrintValues(values: new int[] { 10, 20 });
// Explicitly specify the argument name and provide a single value
PrintValues(values: 10);
// No arguments: default the title, empty array
PrintValues();
}
}

I haven't found a way of specifying multiple values without explicitly building the array though...

Trying to use optional parameters in c#

The problem is that you're using [Optional] instead of the C# language integration for optional parameters. As far as the language is concerned (in terms of the method declaration part), num1 is a required parameter, so it has to come before optInput. The compiler does know about OptionalAttribute when consuming methods, but not when declaring them.

Assuming you wanted both parameters to be optional, use the language integration for both:

public string UserAnswer(string optInput = null, int num1 = 0)

I would strongly advise against using OptionalAttribute explicitly - there's no reason to do so now there's language support, and it's more likely to cause confusion than to help when it comes to anyone else reading the code.

Does C# 4.0 and a combination of optional parameters and overloads give you a warning about ambiguity?

It will compile without warnings and will choose the first overload.

With the introduction of optional and named parameters, the overload resolution mechanism of C# has become really complicated. In this specific case, it makes sense however. As usual, the compiler will choose the most specific overload that matches the arguments.

I don't believe this specific case is much different from C# 1.0:

public void SomeMethod(Int32 x, Int32 y) { } 
public void SomeMethod(Int32 x, Int32 y, params Int32[] z) { }

which works identically (in terms of overload resolution).

Follow up answer: I don't think so. I'm afraid you'll have to manually specify the default argument in the method call. However, if x or y parameter had a different name like:

public void SomeMethod(Int32 x, Int32 y) { } 
public void SomeMethod(Int32 t, Int32 y, Int32 z = 0) { }

you could choose the second overload with:

obj.SomeMethod(t: 10, y: 20);

C# 4.0 optional out/ref arguments

As already mentioned, this is simply not allowed and I think it makes a very good sense.
However, to add some more details, here is a quote from the C# 4.0 Specification, section 21.1:

Formal parameters of constructors, methods, indexers and delegate types can be declared optional:

fixed-parameter:

    attributesopt parameter-modifieropt type identifier default-argumentopt
default-argument:

    = expression

  • A fixed-parameter with a default-argument is an optional parameter, whereas a fixed-parameter without a default-argument is a required parameter.
  • A required parameter cannot appear after an optional parameter in a formal-parameter-list.
  • A ref or out parameter cannot have a default-argument.

Should you declare methods using overloads or optional parameters in C# 4.0?

I'd consider the following:

  • Do you need your code to be used from languages which don't support optional parameters? If so, consider including the overloads.
  • Do you have any members on your team who violently oppose optional parameters? (Sometimes it's easier to live with a decision you don't like than to argue the case.)
  • Are you confident that your defaults won't change between builds of your code, or if they might, will your callers be okay with that?

I haven't checked how the defaults are going to work, but I'd assume that the default values will be baked into the calling code, much the same as references to const fields. That's usually okay - changes to a default value are pretty significant anyway - but those are the things to consider.



Related Topics



Leave a reply



Submit