Named arguments. Advantages. Examples of using named arguments in methods, constructors, indexers, delegates.

Named arguments. Advantages. Examples of using named arguments in methods, constructors, indexers, delegates


Contents


 1. The concept of named arguments. General form

When passing arguments to a method, the order in which they are followed is the same as the order of the parameters defined in the method declaration. When passing an argument to a method, its value is passed to the parameter, which has the same position in the parameter list when the method is declared.

However, C# allows you to change the order in which arguments are passed to the corresponding parameters. In this case, so-called named arguments are used. A named argument is such an argument, that when calling a method contains the name of the parameter to which the value of this argument is passed.

In the case of a method call with a named argument, the following general form must be used to

parameter_name : value

where

  • parameter_name – the name of the parameter to which the value is passed. In this case, the ‘value’ is a named argument;
  • value – named argument. It can be a constant or a type variable that corresponds to the type of the parameter.

The general form of calling a method with one named argument is:

MethodName(parameter_name : argument_name);

where

  • MethodName – the name of the method that is called with the argument_name argument;
  • parameter_name – the name of the parameter of the method that receives the value from argument_name;
  • argument_name – the name of the argument that is passed to parameter_name. The value of argument_name can also be a constant.

 

2. Examples that demonstrate the use of named arguments

Example 1. The Mult() method is specified, receiving 2 integer values and returning their multiplication

// method that returns the result of multiplying 2 numbers
static int Mult(int a, int b)
{
  return a * b;
}

Below is a code that demonstrates a method call with named arguments.

// named arguments
int x = 3, y = 5, z = 7;
int res;

res = Mult(a: x, b: y); // x=>a, y=>b, res = 3*5 = 15
res = Mult(a: 3, b: z); // 3=>a, z=>b, res = 3*7 = 21
res = Mult(b: 11, a: y); // 11=>b, y=a, res = 11*5 = 55

In the above code, the Mult() method is called three times.

The first time the call Mult() as follows:

res = Mult(a: x, b: y);

With this call

  • the value of the variable x is passed to the parameter a of the Mult() method;
  • the value of the variable y is passed to the b parameter of the Mult() method.

The second call to Mult() is as follows:

res = Mult(a: 3, b: z);

In this case:

  • the value of constant 3 is passed to the parameter a of the Mult() method;
  • the value of the variable z is passed to the b parameter of the Mult() method.

The third Mult() call changes the positions of the named arguments in reverse order:

res = Mult(b: 11, a: y);

In this case:

  • the positions of the named arguments are changed: first, the value is set for the parameter b, then for the parameter a. Such a method call is valid according to the syntax of C#;
  • internal parameter b gets the value of constant argument 11;
  • internal parameter a gets the value of the variable argument y.

Example 2. In this example, the Area() method takes 6 named arguments, which are the coordinates of the points of a triangle. The method calculates the area of a triangle.

// the method calculates the area of a triangle given by the coordinates of points
static double Area(double x1, double y1, double x2, double y2, double x3, double y3)
{
  double a, b, c;
  a = Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
  b = Math.Sqrt((x1 - x3) * (x1 - x3) + (y1 - y3) * (y1 - y3));
  c = Math.Sqrt((x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3));

  return a + b + c;
}

When you call a method, the named arguments follow in random order

// calculation the area of a triangle
double area;
area = Area(x3: 3.0, y2: 4, x1: 2, y1: 4, y3: 7, x2: 0); // area = 9.40491834728767

 

3. Does the order matter when using the named arguments in method call?

No, it doesn’t. Named arguments may follow in any order when calling the method.

 

4. Is it possible to use positional (unnamed) arguments together with the named arguments in the method call?

Yes, it is, when provided the following rule:

  • the definition of named arguments should follow the definition of positional (fixed) arguments.

For example. The Min() method is specified that calculates minimum between three numbers.

// calculation of the minimum between 3 numbers
static int Min(int a, int b, int c)
{
  int min = a;
  if (min > b) min = b;
  if (min > c) min = c;
  return min;
}

Calling the Min() method will be correct only when the named arguments follow after the fixed (normal) arguments, as shown below

int x, y, z;
x = 5;
y = 8;
z = -3;

int min;

// error: after the fixed argument z follow the named argument c: x
// min = Min(a: y, z, c: x);

// correct: first are fixed arguments y, z follow, then named argument c: x
min = Min(y, z, c: x); // min = -3

// correct: all arguments are the named arguments
min = Min(c: x, b: y, a: z); // min = -3

 

5. Can a named argument take a value several times when calling a method?

No, it can not. A named argument can only be used once when calling a method.

For example. For the Min() method, which calculates a minimum between three integer parameters

// searching for a minimum between 3 numbers
static int Min(int a, int b, int c)
{
  int min = a;
  if (min > b) min = b;
  if (min > c) min = c;
  return min;
}

the following call

// error: named argument cannot be specified multiple times
min = Min(a: x, a: y, b: z);

will generate the error

Named argument 'a' cannot be specified multiple times

 

6. What elements of C# can use named arguments?

Named arguments can be used in:

  • methods;
  • delegates;
  • class constructors;
  • indexers.

 

7. What are the advantages of using named arguments?

The use of named arguments provides the following interrelated advantages:

  • calls to complex methods with many parameters are simplified when combining fixed and named arguments;
  • the visibility of method calls that require multiple arguments with complex names is increased;
  • named arguments are useful in cases where extra verbosity (informativeness) is needed when calling methods.

 

8. An example of using named arguments in class constructors

A CPoint class is defined that describes a point on the coordinate plane. The class contains a constructor that takes two parameters.

// class that implements a point on the coordinate plane
class CPoint
{
  double x, y;

  // class constructor
  public CPoint(double x, double y)
  {
    this.x = x;
    this.y = y;
  }

  // access methods
  // method that takes optional arguments
  public void SetXY(double x = 0, double y = 0)
  {
    this.x = x;
    this.y = y;
  }

  // get the value of x,y
  public void GetXY(out double x, out double y)
  {
    x = this.x;
    y = this.y;
  }
}

Then the use of class constructors with named arguments can be as follows:

// constructor call with named arguments
CPoint pt1 = new CPoint(y: 1, x: 2.5);

// constructor call with fixed arguments
CPoint pt2 = new CPoint(2, 3.8);

// constructor call with one fixed argument and one named argument
CPoint pt3 = new CPoint(2.2, y: 1.5);

// checking
double x, y;

pt1.GetXY(out x, out y); // x = 2.5, y = 1.0
pt2.GetXY(out x, out y); // x = 2.0, y = 3.8
pt3.GetXY(out x, out y); // x = 2.2, y = 1.5

// calling a method that gets both named and optional arguments at the same time
pt1.SetXY(y: 3.3); // x = 0, y = 3.3
pt1.GetXY(out x, out y);

In the above example, the CPoint constructor is invoked three times for different cases.

 

9. An example of using named arguments in a delegate

A delegate type TInt declaration is given, which:

  • accepts two integer parameters;
  • returns an integer parameter.
// declare the delegate type TInt
delegate int TInt(int a, int b);

There are two static method declarations that operate with integer parameters a, b.

// methods of processing integers
// multiplication of integers
static int Mult(int a, int b)
{
  return a * b;
}

// addition of integers
static int Add(int a, int b)
{
  return a + b;
}

The following demonstrates the use of named arguments in the TInt type delegate to invoke methods.

// declare a delegate of type tInt
TInt ti;
int res; // calculation result

// add method to delegate
ti = Mult;

// invoke the delegate with a named parameter
res = ti(b: 4, a: 7); // res = 28

ti = Add;
res = ti(2, b: 11); // res = 13

 

10. An example of using named arguments in indexers

An Array class is specified that implements an array of integers. In the class are declared:

  • two constructors;
  • one indexer.

 

// class of Array type
class Array
{
  int[] A; // internal variable - array

  // class constructors
  public Array()
  {
    A = null;
  }

  public Array(int size)
  {
    A = new int[size];
    for (int i = 0; i < A.Length; i++)
      A[i] = i;
  }

  // indexers
  public int this[int index]
  {
    get
    {
      if ((A != null) && (A.Length > 0) && (index >= 0) && (index < A.Length))
      return A[index];
      return 0;
    }

    set
    {
      if (A == null)
        return;
      if (A.Length > 0)
        A[index] = value;
    }
  }
}

The following is program code that demonstrates the use of an Array class indexer that accepts a named argument

// create an instance of the Array class
Array A1 = new Array(10);

// use the indexer with a named argument
int t;
t = A1[index: 3]; // t = A[3] = 3 - using the named argument
t = A1[8]; // t = 8 - fixed argument

A1[index: 5] = 13;
t = A1[5]; // t = 13

 

11. Is it possible to combine named and optional arguments in a method call?

Yes, it is.

For example. The Average3() method is specified, which determines the arithmetic average between three values a, b, c which are input parameters. All three parameters a, b, c are optional arguments. They get different values: a = 1, b = 2, c = 3.

// method containing optional arguments
static double Average3(int a = 1, int b = 2, int c = 3)
{
  return (a + b + c) / 3.0;
}

You can call this method in various ways, combining named and optional arguments:

// combining optional arguments with named arguments
double res;

// one named argument (b), two optional arguments (a, c)
res = Average3(b: 5); // res = Average3(1, 5, 3) = 3

// two named arguments (a, b), one optional argument (c)
res = Average3(a: 8, b: 4); // res = Average3(8, 4, 3) = 5

// one named argument (c), two optional arguments (a,b)
res = Average3(c: 10); // res = Average3(1, 2, 10) = 4.3333333333

// two named arguments (a,c), one optional argument (b)
res = Average3(c: 7, a: 1); // res = Average3(1, 2, 7) = 3.3333333333


Related topics