litterbugkid
litterbugkid

Reputation: 3666

Using optional arguments

I have a method with 2 optional parameters.

public IList<Computer> GetComputers(Brand? brand = null, int? ramSizeInGB = null)
{
    return new IList<Computer>();
}

I'm now trying to use this method elsewhere where I do not want to specify the Brand argument and just the int but I'm getting errors using this code:

_order.GetComputers(ram);

Errors I am receiving:

Error   1   The best overloaded method match for 'ComputerWarehouse.Order.GetComputers(ComputerWarehouse.Brand?, int?)' has some invalid arguments  C:\Users\avmin!\Documents\InnerWorkings Content\630dd6cf-c1a2-430a-ae2d-2bfd995881e7\content\T0062A2-CS\task\ComputerWarehouse\ComputerStore.cs 108 59  ComputerWarehouse
Error   2   Argument 1: cannot convert from 'int?' to 'ComputerWarehouse.Brand?'    C:\Users\avmin!\Documents\InnerWorkings Content\630dd6cf-c1a2-430a-ae2d-2bfd995881e7\content\T0062A2-CS\task\ComputerWarehouse\ComputerStore.cs 108 79  ComputerWarehouse

Upvotes: 4

Views: 339

Answers (3)

SWeko
SWeko

Reputation: 30912

The correct syntax is to use named arguments in conjunction with optional parameters, like this:

_order.GetComputers(ramSizeInGB: ram);

Optional parameters can be skipped (without using named arguments) only when they are positioned after the specified arguments, so this would be ok:

_order.GetComputers(new Brand());

as would this

_order.GetComputers();

To see why this must be done in this way, consider a method with a signature like this:

public void Method(double firstParam = 0, long secondParam = 1)

Method(3);

Here the compiler cannot infer if a developer meant to call the method with the first parameter, or with the second parameter, so the only way to distinct is to say explicitly what arguments map to what parameters.

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1503200

To allow earlier arguments to be filled in by the compiler, you need to specify the names of later ones:

_order.GetComputers(ramSizeInGB: ram);

Basically, the C# compiler assumes that unless you specify any argument names, the arguments you provide are in additional order. If you don't provide values for all the parameters, and the remaining parameters have defaults, those defaults will be used.

So all of these are valid (assuming appropriate values of brand and ram):

_order.GetComputers(brand, ram);       // No defaulting
_order.GetComputers(brand);            // ramSizeInGB is defaulted
_order.GetComputers(brand: brand);     // ramSizeInGB is defaulted
_order.GetComputers(ramSizeInGB: ram); // brand is defaulted
_order.GetComputers();                 // Both arguments are defaulted

Upvotes: 5

Seth Flowers
Seth Flowers

Reputation: 9190

You have to specify the name of the optional argument if you are going to skip other optional arguments.

_order.GetComputers(ramSizeInGB: ram);

Upvotes: 9

Related Questions