<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. C#
  3. Arrays and methods
All lessons in this course

Lesson 14 of 60 16 minBeginner

Parameters: ref, out, in, params, optional, named

Understand how arguments are passed to methods and use every kind of parameter C# offers.

In the methods lesson every parameter was a simple input. C# gives you more control: change the caller’s variable, return several values, accept any number of arguments, and skip arguments that have sensible defaults.

By value (the default)

Normally a method receives a copy of each argument. Changing the parameter inside the method does not change the caller’s variable. Step through the diagram, then switch to ref and out:

Interactive

Copy or the same box?

Params.cs
static void AddBonus(int x){    x = x + 10;} int score = 50;AddBonus(score);Console.WriteLine($"score = {score}");
Main
score50
AddBonus
not called
Step 1 / 4
score is created in Main with the value 50.

ref: let the method change your variable

Swap.cs
static void Swap(ref int a, ref int b){    int temp = a;    a = b;    b = temp;} int x = 1, y = 2;Swap(ref x, ref y);           // ref is required at the call tooConsole.WriteLine($"x={x}, y={y}");
Output
x=2, y=1
  • The variable must have a value before the call.
  • You must write ref in both the method and the call, so readers can see the variable may change.

out: return extra values

An out parameter is an output. The method must assign it before returning, and the caller doesn’t need to set it first. You have already used this: int.TryParse(text, out int n).

MinMax.cs
static void MinMax(int[] values, out int min, out int max){    min = values[0];    max = values[0];    foreach (int v in values)    {        if (v < min) min = v;        if (v > max) max = v;    }} MinMax(new[] { 7, 2, 9, 4 }, out int lo, out int hi);   // declare inlineConsole.WriteLine($"min {lo}, max {hi}");
Output
min 2, max 9

in: read-only by reference

in passes a reference (no copy) but the method may not change it. It is a performance tool for large structs, such as a 3D matrix, that would be expensive to copy. For int or double it brings no benefit.

In.cs
static double Length(in Vector3 v)    // no copy of the struct{    // v.X = 0;  // error: an 'in' parameter is read-only    return Math.Sqrt(v.X * v.X + v.Y * v.Y + v.Z * v.Z);}

params: any number of arguments

Params.cs
static int Sum(params int[] numbers){    int total = 0;    foreach (int n in numbers) total += n;    return total;} Console.WriteLine(Sum());                 // 0Console.WriteLine(Sum(5));                // 5Console.WriteLine(Sum(1, 2, 3, 4));       // 10Console.WriteLine(Sum(new[] { 10, 20 })); // an array works too
Output
0
5
10
30

params must be the last parameter, and there can be only one. Console.WriteLine("{0} {1}", a, b) and string.Join use it.

Optional parameters

Optional.cs
static void Greet(string name, string greeting = "Hello", int times = 1){    for (int i = 0; i < times; i++)        Console.WriteLine($"{greeting}, {name}!");} Greet("Ravi");                    // uses both defaultsGreet("Ravi", "Welcome");         // times = 1Greet("Ravi", "Hi", 2);
Output
Hello, Ravi!
Welcome, Ravi!
Hi, Ravi!
Hi, Ravi!

Optional parameters have a default value and must come after all required ones. The default must be a compile-time constant (a number, string, null, true…).

Named arguments

Named.cs
Greet("Ravi", times: 3);                       // skip greeting, set timesGreet(times: 2, name: "Selva");                // any orderCreateBeam(length: 6.0, depth: 0.45, width: 0.2);   // self-explaining call

Naming arguments lets you skip optional ones in the middle, and makes calls with several numbers much easier to read: compare CreateBeam(6.0, 0.45, 0.2).

Summary

KindCaller writesMust be set before call?Method may change it?
value (default)F(x)yesonly its own copy
refF(ref x)yesyes, changes the caller’s variable
outF(out x)nomust assign it
inF(x) or F(in x)yesno (read-only)
paramsF(1, 2, 3)–it is a new array
optionalF() or F(5)–its own copy
Quick check

Which parameter kind must the method assign before it returns?

Quick check

Is static void F(int a = 1, int b) valid?

Practice

Write static bool TryDivide(int a, int b, out int result) that returns false (and sets result to 0) when b is 0, otherwise stores a / b in result and returns true. Call it for 10 / 2 and 5 / 0.

Show the solution
Solution.cs
static bool TryDivide(int a, int b, out int result){    if (b == 0)    {        result = 0;        return false;    }    result = a / b;    return true;} if (TryDivide(10, 2, out int r1)) Console.WriteLine(r1);if (!TryDivide(5, 0, out _)) Console.WriteLine("Cannot divide by zero");
Output
5
Cannot divide by zero

Remember

  • By default arguments are copied (passed by value).
  • ref shares the caller’s variable; out returns an extra value; in is read-only by reference.
  • params accepts any number of arguments as an array (last parameter only).
  • Optional parameters have defaults; named arguments make calls clear.
0 of 60 lessons completed