C# Programming Tutorial 0/45 lessons ~6 min read Lesson 12

    Methods

    Methods encapsulate behavior — parameters in, return values out, optional ref/out/in modifiers for advanced scenarios.

    Course progress0%
    Focus
    10 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Methods encapsulate behavior — parameters in, return values out, optional ref/out/in modifiers for advanced scenarios. Well-designed methods follow Single Responsibility: one reason to change, clear naming, and minimal side effects.

    C# supports overloading (next lesson), local functions, expression-bodied members, and static methods for pure utilities. Async methods return Task or ValueTask. Interviewers probe pass-by-value vs reference, default parameters, and params arrays.

    Enterprise services expose methods on interfaces; DI containers inject implementations. This lesson builds method fundamentals before OOP layers.

    The story

    When a customer withdraws cash at an ATM, the system must verify the amount is valid and does not exceed the balance — without throwing exceptions for ordinary "insufficient funds" cases. A TryWithdraw method returns false and leaves the balance unchanged when the withdrawal fails, which is exactly how real banking APIs communicate expected failures.

    Understanding the topic

    Key concepts

    • Signature: access modifier, return type, name, parameters.
    • Pass by value copies reference or struct bits; ref passes alias.
    • out for multiple returns; TryParse pattern.
    • Optional parameters with defaults; named arguments at call site.
    • params T[] for variable argument lists.
    • Local functions capture outer scope — useful for validation helpers.

    Step-by-step explanation

    1. Caller pushes arguments per calling convention.
    2. Method frame allocated on stack with locals.
    3. return exits and optionally supplies value.
    4. void methods for side effects; prefer returning Result types.
    5. Expression body => for one-liners.
    6. Static methods cannot access instance members.

    Practical code example

    Try-style method with out parameter and local function validation:

    csharp
    namespace TechLearningPro.Methods;
    public static class WithdrawalService
    {
    public static bool TryWithdraw(decimal balance, decimal amount, out decimal newBalance)
    {
    newBalance = balance;
    if (!IsValidAmount(amount))
    return false;
    if (amount > balance)
    return false;
    newBalance = balance - amount;
    return true;
    static bool IsValidAmount(decimal value) => value is > 0 and <= 1_000_000m;
    }
    }

    Line-by-line code explanation

    • TryWithdraw(decimal balance, decimal amount, out decimal newBalance) follows the Try-pattern: bool success plus an output parameter.
    • newBalance = balance initializes the out parameter before any early exit.
    • if (!IsValidAmount(amount)) return false rejects zero, negative, or absurdly large amounts.
    • if (amount > balance) return false handles insufficient funds without an exception.
    • newBalance = balance - amount computes the updated balance only when the withdrawal succeeds.
    • return true signals success to the caller.
    • static bool IsValidAmount(decimal value) is a local function scoped inside the method.
    • value is > 0 and <= 1_000_000m uses a relational pattern for concise range validation.

    Key takeaway: Try pattern avoids exceptions for expected failures. static local function cannot capture instance — pure validation.

    Real-world use

    Where you'll use this in production

    • Domain services with Try* methods for business rule failures.
    • Utility libraries with static helper methods.
    • Repository interfaces with CRUD method contracts.
    • Extension methods adding behavior to existing types (later lesson).

    Best practices

    • Methods under 20 lines; extract when growing.
    • Use Try pattern instead of exceptions for control flow.
    • Avoid ref unless interop or high-performance APIs.
    • Name methods with verbs: CalculateTotal, ValidateInput.
    • Document preconditions with ArgumentException throws.

    Common mistakes

    • Too many parameters — use parameter object record.
    • Side effects in methods named Get*.
    • Returning null instead of Try or Option pattern.
    • public void methods that should return bool success.

    Advanced interview questions

    Q1BeginnerPass by value in C#?
    Copy of value type bits or copy of reference — both callee changes don't affect caller reference for objects unless ref.
    Q2BeginnerPurpose of out parameter?
    Return secondary value; caller must assign before use; TryParse idiom.
    Q3Intermediateref vs out?
    ref requires initialized variable; out must be assigned in method before return.
    Q4IntermediateWhen use local functions?
    Private helpers scoped to one method; static local avoids closure allocation.
    Q5AdvancedDesign method signatures for idempotent payment capture.
    CapturePayment(orderId, idempotencyKey) returns Result; document duplicate key returns existing receipt.

    Summary

    Methods bundle reusable logic with clear signatures. Try/out pattern handles expected failures gracefully. Keep methods small, named with verbs, minimal side effects. Local functions and expression bodies reduce noise. Next: method overloading and compile-time dispatch.

    Ready to mark this lesson complete?Track your journey across the entire course.