Lesson 77 min read

Methods

Write once, use everywhere — the power of reusable code

What Is a Method?

A method is a recipe. You give it a name ("MakePancakes"), list the ingredients it needs (parameters), and write the steps (the body). Then, whenever you want pancakes, you just call the recipe by name instead of rewriting all the steps.

Methods help you:

  • Avoid repetition — write it once, call it 100 times
  • Organize code — break big problems into small, named chunks
  • Test easily — you can test each method on its own

When you call a method, C# pushes it onto the call stack; when it returns, it pops off. Every method has a return type (what it gives back) and can take parameters (what you give it). If it doesn't return anything, its return type is void.

Basic Methods

// Method that returns a value
static int Add(int a, int b)
{
return a + b;
}
// Method that returns nothing (void)
static void Greet(string name)
{
Console.WriteLine($"Hello, {name}! Welcome aboard.");
}
// Expression-bodied method (short version with =>)
static double CircleArea(double radius) => Math.PI * radius * radius;
// Calling the methods
int sum = Add(5, 3);
Console.WriteLine($"5 + 3 = {sum}");
Greet("Luna");
double area = CircleArea(5);
Console.WriteLine($"Circle area (r=5): {area:F2}");
Output
5 + 3 = 8
Hello, Luna! Welcome aboard.
Circle area (r=5): 78.54

Parameters: ref, out, and Optional

Normally, when you pass a variable to a method, C# sends a copy. The method can't change the original. But sometimes you want the method to modify the original — that's where ref and out come in.

  • ref — "I'm lending you my actual variable. You can read AND change it." The variable must be initialized before passing.
  • out — "I'm giving you an empty box. You MUST fill it." The variable doesn't need to be initialized before passing.
  • Optional parameters — parameters with default values. If the caller doesn't provide them, the default kicks in.

ref, out, and Optional Parameters

// ref — modifies the original variable
static void DoubleIt(ref int number)
{
number *= 2;
}
// out — must assign a value inside the method
static void Divide(int a, int b, out int quotient, out int remainder)
{
quotient = a / b;
remainder = a % b;
}
// Optional parameters with defaults
static string MakeTag(string text, string color = "blue", int size = 14)
{
return $"<span style='color:{color}; font-size:{size}px'>{text}</span>";
}
// Using ref
int value = 10;
DoubleIt(ref value);
Console.WriteLine($"After DoubleIt: {value}");
// Using out
Divide(17, 5, out int q, out int r);
Console.WriteLine($"17 / 5 = {q} remainder {r}");
// Using optional params
Console.WriteLine(MakeTag("Hello")); // uses defaults
Console.WriteLine(MakeTag("Warning", "red")); // override color
Console.WriteLine(MakeTag("Title", "green", 24)); // override both
Output
After DoubleIt: 20
17 / 5 = 3 remainder 2
<span style='color:blue; font-size:14px'>Hello</span>
<span style='color:red; font-size:14px'>Warning</span>
<span style='color:green; font-size:24px'>Title</span>

Method Overloading — Same Name, Different Signatures

// Same method name, different parameter lists
static string Describe(int number)
=> $"{number} is a whole number";
static string Describe(double number)
=> $"{number} is a decimal number";
static string Describe(string text)
=> $"\"{text}\" is a string with {text.Length} characters";
static string Describe(int a, int b)
=> $"{a} and {b} add up to {a + b}";
// C# picks the right overload based on what you pass
Console.WriteLine(Describe(42));
Console.WriteLine(Describe(3.14));
Console.WriteLine(Describe("hello"));
Console.WriteLine(Describe(10, 20));
Output
42 is a whole number
3.14 is a decimal number
"hello" is a string with 5 characters
10 and 20 add up to 30
Note: 🎯 Expression-bodied members (=>) are perfect for one-liner methods. But if your method has more than one statement, use the regular { } block. Don't cram complex logic into an arrow — readability wins over cleverness.

Quick check

What does 'void' mean as a return type?
Arrays & ListsClasses & Objects