iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Methods

C# methods: signatures, parameters, overloads, optional + named args, ref / out / in, and the patterns that age well.

C# — methods

EXAMPLE
// ===== Basic signature =====
public int Add(int a, int b) => a + b;
public static int Sum(IEnumerable<int> xs) => xs.Sum();

// Expression-bodied for one-liners; braces for multi-line.

// ===== Overloads =====
public int Add(int a, int b) => a + b;
public double Add(double a, double b) => a + b;
public int Add(int a, int b, int c) => a + b + c;

// Compiler picks the best match by arg types + count.

// ===== Optional parameters =====
public string Greet(string name, string greeting = "Hello") => $"{greeting}, {name}";
Greet("Alex");                     // 'Hello, Alex'
Greet("Alex", "Hi");               // 'Hi, Alex'

// ===== Named arguments =====
SendEmail(to: "a@x.io", subject: "hi", body: "hello", priority: 5);
// Useful for methods with many params or all-optional ones.

// ===== params (variadic) =====
public int Sum(params int[] xs) {
    int s = 0; foreach (var x in xs) s += x; return s;
}
Sum(1, 2, 3, 4);                   // 10
Sum(new[] { 1, 2, 3 });            // 6 (still works)

// ===== ref / out / in =====
public bool TryParse(string s, out int value) {
    if (int.TryParse(s, out value)) return true;
    value = 0; return false;
}
if (TryParse("42", out var n)) Console.WriteLine(n);

public void Swap(ref int a, ref int b) { (a, b) = (b, a); }

// in: pass by readonly reference (avoids copy of large structs)
public double Distance(in Point p1, in Point p2) { /* ... */ }

// ===== Async =====
public async Task<string> FetchAsync(string url) {
    using var http = new HttpClient();
    return await http.GetStringAsync(url);
}

// Always return Task / Task<T> / ValueTask for async; never async void (except event handlers).

// ===== Local functions =====
public IEnumerable<int> Doubled(IEnumerable<int> xs) {
    return xs.Select(Inner);
    int Inner(int n) => n * 2;
}

// ===== Extension methods =====
public static class StringExt {
    public static bool IsEmpty(this string? s) => string.IsNullOrEmpty(s);
}
"hello".IsEmpty();         // false (extension methods feel like instance methods)

// ===== Generics =====
public static T First<T>(IReadOnlyList<T> xs) => xs[0];
public static TResult Map<TIn, TResult>(TIn x, Func<TIn, TResult> f) => f(x);

// Constraints:
public static T Max<T>(T a, T b) where T : IComparable<T>
    => a.CompareTo(b) >= 0 ? a : b;

// ===== Patterns to internalise =====
// - Expression-bodied members for one-liners
// - Named args when there are 3+ parameters
// - TryX pattern with bool return + out value
// - async all the way down at I/O boundaries
// - Extension methods for fluent APIs

// ===== Pitfalls =====
// - async void (except event handlers) -> unobservable exceptions
// - Default param values change with re-compile cascading (callers may pick up new defaults)
// - Overuse of out -> hard to read; prefer tuples ($"Try{Name}")
// - Capturing this in delegates -> retain references longer than expected

Why it matters

C# methods are dense in features: overloads, optional + named args, params, ref/out/in, async, generics, extensions. Use expression-bodied for short, named args for clarity, TryX for safe parsing, and async at the IO boundary. The language rewards small, focused methods.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
static int Add(int a, int b) => a + b;
static int Add(int a, int b, int c) => a + b + c;   // overload
Console.WriteLine(Add(2, 3));
Try it Yourself »

Exercise

Expression-bodied method.

static int Add(int a, int b) a + b;

Discussion

Loading…