0Pricing
C# Academy · Lesson

Guard & validation patterns

Validate inputs early with guard clauses, throw the right exceptions, and use TryParse-style checks for user data.

Guard & validation patterns is a free C# Academy lesson on CoddyKit — lesson 3 of 3. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, one of 3 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why guards

Aim: Keep methods safe and readable.

  • Use guard clauses at the top
  • Throw specific exceptions (ArgumentNullException, ArgumentOutOfRangeException)
  • Use TryParse for user input
  • Fail fast; avoid deep nesting

Early guards demo

Add small checks at the top to validate arguments; throw specific exceptions so callers know what went wrong.

using System;

// Demo: validate inputs at the top; keep main logic flat.
public class Program
{
  // Compute price with simple rules; guard early.
  public static decimal ComputePrice(string sku, int qty, decimal unitPrice)
  {
    if (sku == null) throw new ArgumentNullException("sku");
    if (sku.Length == 0) throw new ArgumentException("sku must not be empty", "sku");
    if (qty <= 0) throw new ArgumentOutOfRangeException("qty", "qty must be > 0");
    if (unitPrice < 0m) throw new ArgumentOutOfRangeException("unitPrice", "unitPrice must be >= 0");

    // Main logic stays simple
    decimal subtotal = qty * unitPrice;
    if (qty >= 10) subtotal = subtotal * 0.9m; // small bulk discount
    return subtotal;
  }

  public static void Main(string[] args)
  {
    Console.WriteLine(ComputePrice("ABC", 2, 5m));   // ok
    try { Console.WriteLine(ComputePrice("", 2, 5m)); } catch (Exception ex) { Console.WriteLine(ex.GetType().Name); }
  }
}

Guard helper class

Extract common checks into a small Guard class to keep method bodies clean and consistent.

using System;

// Minimal static helper for common validations (beginner friendly).
public static class Guard
{
  public static void NotNull(object value, string name)
  {
    if (value == null) throw new ArgumentNullException(name);
  }

  public static void NotNullOrEmpty(string value, string name)
  {
    if (value == null) throw new ArgumentNullException(name);
    if (value.Length == 0) throw new ArgumentException(name + " must not be empty", name);
  }

  public static void InRange(int value, int minInclusive, int maxInclusive, string name)
  {
    if (value < minInclusive || value > maxInclusive)
      throw new ArgumentOutOfRangeException(name, "Expected " + minInclusive + ".." + maxInclusive);
  }
}

public class Program
{
  static int ScoreFor(string userId, int level)
  {
    Guard.NotNullOrEmpty(userId, "userId");
    Guard.InRange(level, 1, 10, "level");
    // pretend logic
    return level * 100;
  }

  public static void Main(string[] args)
  {
    Console.WriteLine(ScoreFor("u42", 3));
    try { Console.WriteLine(ScoreFor(null, 3)); } catch (Exception ex) { Console.WriteLine(ex.GetType().Name); }
  }
}

TryParse validation

For routine invalid input, prefer TryParse-style methods that return false instead of throwing exceptions.

using System;

// Use TryParse for user-provided text; avoid throwing for normal invalid input.
public class Program
{
  public static bool TryGetPort(string text, out int port)
  {
    port = 0;
    int value;
    if (!int.TryParse(text, out value)) return false;
    if (value < 1 || value > 65535) return false;
    port = value;
    return true;
  }

  public static void Main(string[] args)
  {
    int p;
    Console.WriteLine("8080 -> " + (TryGetPort("8080", out p) ? ("ok " + p) : "invalid"));
    Console.WriteLine("abc -> " + (TryGetPort("abc", out p) ? ("ok " + p) : "invalid"));
  }
}

Throw vs return

  • Throw for programmer errors (bad API usage, null where not allowed, out-of-range)
  • Return false/Result for normal user mistakes (invalid text)
  • Use specific exception types; include the parameter name
  • Validate outside-in: cheap checks first

Best practices

Tips:

  • Validate at boundaries (controllers, public APIs)
  • Prefer small guard methods over deep nesting
  • Keep error messages short and clear
  • Log once at the boundary, not in every guard

Guard clause meaning

Quick check: What best describes a guard clause?

Recap

Recap: Validate early with guard clauses, throw specific exceptions for programmer errors, and use TryParse for everyday user input.

Frequently asked questions

Is the “Guard & validation patterns” lesson free?

Yes — the full text of “Guard & validation patterns” is free to read here on the web, and the C# Academy course includes 3 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO.

What will I learn in “Guard & validation patterns”?

Validate inputs early with guard clauses, throw the right exceptions, and use TryParse-style checks for user data. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 3, so you can start here or from the beginning and move at your own pace.

How long does the “Guard & validation patterns” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Logging abstractions, Debug/Trace
  2. Basic profiling & traces (concepts)
  3. Guard & validation patterns
← Back to C# Academy