Skip to main content
ANVISoftware Solutions
Lesson 16 of 62Beginner14 min

Creating Methods

By the end of this lesson

Define methods with clear names, inputs and return types.

A method is a named piece of work. You give it what it needs, it does one thing, and it hands back a result.

In C# every method lives inside a type. Even when you write one next to your top-level statements, the compiler is placing it inside a class for you.

Program.cs — the anatomy of a method
C#
decimal net = CalculateNet(4, 12.50m);
Console.WriteLine($"Net: {net:N2}");

static decimal CalculateNet(int quantity, decimal unitPrice)
{
    return quantity * unitPrice;
}
  • The parts, in order: the return type (decimal), the name (CalculateNet), then the parameters in brackets.
  • return hands a value back to the caller and ends the method at that point.
  • A method written beside top-level statements is a local function, and it can be called from a line above its declaration. static here means it cannot read the variables around it, which is what you want for a calculation.
  • Method names in C# are PascalCase — an initial capital on each word — while parameters and locals are camelCase.

Methods that belong to a type

C#
decimal vat = InvoiceCalculator.CalculateVat(1240.50m, 0.20m);

Console.WriteLine($"VAT: {vat:N2}");
Console.WriteLine(InvoiceCalculator.Describe(1240.50m));

public static class InvoiceCalculator
{
    public static decimal CalculateVat(decimal net, decimal rate)
    {
        return Math.Round(net * rate, 2, MidpointRounding.AwayFromZero);
    }

    public static string Describe(decimal net) =>
        net >= 1000m ? "Large invoice" : "Standard invoice";
}
  • Most methods live in a class rather than beside your top-level statements. A static class is a reasonable home for calculations that need no object state.
  • public makes the method callable from other files. static means you call it on the type name, InvoiceCalculator.CalculateVat, rather than on an object.
  • Describe uses => in place of braces and return. When the entire body is one expression, that form removes two lines and means exactly the same thing.
  • MidpointRounding.AwayFromZero is there because tax rules usually say a half rounds up, while the default sends halves to the nearest even number.

Turning an existing block of code into a method:

  1. Name the outcome

    Decide what the block produces or does, and name the method after that. Struggling to name it is a signal the block is doing more than one thing.

  2. Find the inputs

    Every value the block reads from the surrounding code becomes a parameter. If the list is getting long, the block may be doing too much.

  3. Find the output

    The one value it produces becomes the return type. Two unrelated outputs usually means two methods.

  4. Move it and call it

    Replace the original block with a call. Behaviour should be identical, which makes this a safe change to make before adding anything new.

What separates a method that helps from one that gets in the way:

  • The name says what it produces or does: CalculateVat, FindOverdueInvoices, SendReminder
  • One job. If the name needs the word "and", it is two methods
  • No surprises. A method called GetTotal should not also save anything or send anything
  • Short enough to read without scrolling. When it will not fit on a screen, some part of it has its own name waiting
  • Returns a value rather than changing something elsewhere, wherever that is possible — a method that only calculates can be checked by calling it

Summary

  • A method's signature is its name plus the parameters; the return type says what comes back
  • Methods always live in a type, even the local functions you write beside top-level statements
  • static methods are called on the type; instance methods need an object
  • A name lets the reader work at the level they need, which matters more than reuse
  • Return values rather than printing or setting fields, so the caller decides what happens next

Practice

Attempt each one before opening the solution. Getting it wrong first is how the idea sticks.

Try it yourself

Try it yourself

You have a block that adds up a list of line totals, applies a 5 per cent discount when the subtotal reaches 500, and prints the result.

Turn it into a method that returns the amount due, leaving the printing to the caller. Decide what its parameters should be before you write the signature.

Show solution

The list is the only input, so it is the only parameter. Reading the list from the surrounding code instead would tie the method to one caller and make it untestable.

Returning the amount rather than printing it means the same method can feed a console, an invoice or a test. That single decision is most of what makes a method reusable.

The discount threshold is a literal here. Once a second method needs the same number, it belongs in a const or a configuration value rather than being typed twice.

C#
List<decimal> lineTotals = new List<decimal> { 240m, 180m, 320m };

Console.WriteLine($"Amount due: {CalculateAmountDue(lineTotals):N2}");

static decimal CalculateAmountDue(List<decimal> lineTotals)
{
    decimal subtotal = 0m;

    foreach (decimal lineTotal in lineTotals)
    {
        subtotal += lineTotal;
    }

    decimal discountRate = subtotal >= 500m ? 0.05m : 0m;

    return subtotal - (subtotal * discountRate);
}

Think about it

Think about it

Two methods produce the same figure. One returns it; the other prints it to the console.

Why is the first far easier to check for correctness, even before you have written any tests?

Show solution

A returned value can be compared against an expected one, in a test or in a single line at the console. The check is one expression.

To check the printing version you have to capture console output, or read it with your eyes, and neither can be repeated automatically. The answer exists only as text on a screen.

There is a deeper reason: the printing version has decided how its answer will be used. The returning version leaves that to the caller, so the same calculation serves a report, an API response and a test without being edited.

Saved in this browser only.