{
 "nbformat": 4,
 "nbformat_minor": 5,
 "metadata": {
  "language_info": {
   "name": "csharp"
  }
 },
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "# Error Handling and Validation\n\nPrograms fail in predictable ways: bad input, missing files, unexpected values, and invalid assumptions.\nGood software does not pretend errors never happen — it handles them deliberately.",
   "id": "14356503"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Validation vs. Exceptions\n\n- **Validation** checks expected bad input *before* doing risky work.\n- **Exceptions** handle unexpected failures *at runtime*.\n\nValidation should be your first line of defense. Exceptions are a fallback for when something still goes wrong.",
   "id": "9e949d3e"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Basic `try` / `catch` / `finally`\n\nUse `finally` for cleanup (closing resources, resetting state):",
   "id": "98f55d74"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "try\n{\n    Console.Write(\"Enter a number: \");\n    int value = int.Parse(Console.ReadLine()!);\n    Console.WriteLine($\"You entered {value}\");\n}\ncatch (FormatException)\n{\n    Console.WriteLine(\"Input must be a whole number.\");\n}\ncatch (OverflowException)\n{\n    Console.WriteLine(\"Number is outside the valid int range.\");\n}\nfinally\n{\n    Console.WriteLine(\"Input attempt complete.\");\n}",
   "id": "b53e50b6"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Prefer `TryParse` for User Input\n\nIf invalid input is *expected*, avoid throwing exceptions entirely:",
   "id": "2c20c6f0"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "Console.Write(\"Enter age: \");\nstring raw = Console.ReadLine() ?? \"\";\n\nif (int.TryParse(raw, out int age) && age >= 0)\n{\n    Console.WriteLine($\"Age recorded: {age}\");\n}\nelse\n{\n    Console.WriteLine(\"Please enter a non-negative whole number.\");\n}",
   "id": "d00bac38"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "**Guideline:**\n- Use `TryParse` for normal input flow where bad input is common.\n- Use `try/catch` around operations that can fail unpredictably (file I/O, network, external dependencies).",
   "id": "93270f47"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## File I/O with Safe Handling\n\nCatch specific exception types before broad ones:",
   "id": "e71653bc"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "string path = \"scores.txt\";\n\ntry\n{\n    using StreamReader reader = new StreamReader(path);\n    string? line;\n    while ((line = reader.ReadLine()) != null)\n        Console.WriteLine(line);\n}\ncatch (FileNotFoundException)\n{\n    Console.WriteLine($\"Could not find file: {path}\");\n}\ncatch (UnauthorizedAccessException)\n{\n    Console.WriteLine(\"Permission denied while reading the file.\");\n}\ncatch (IOException ex)\n{\n    Console.WriteLine($\"I/O error: {ex.Message}\");\n}",
   "id": "bd8912f5"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Throwing Exceptions Intentionally\n\nThrow when an API is used incorrectly and execution should stop:",
   "id": "7397dba4"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "static double Divide(double numerator, double denominator)\n{\n    if (denominator == 0)\n        throw new ArgumentException(\"Denominator cannot be zero.\", nameof(denominator));\n\n    return numerator / denominator;\n}\n\nConsole.WriteLine(Divide(10, 2));   // 5\nConsole.WriteLine(Divide(10, 0));   // throws",
   "id": "1c51443d"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "This is better than returning meaningless sentinel values that hide bugs.",
   "id": "4bc96ab1"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Error Message Quality\n\n| Bad | Better |\n|-----|--------|\n| `\"Error happened\"` | `\"Could not open 'scores.txt'. Check that the file exists and that you have read permission.\"` |\n\nGood error messages are: **specific**, **user-actionable**, and free of raw internal noise.",
   "id": "0ddf0a51"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Common Mistakes\n\n- Catching `Exception` everywhere and ignoring details\n- Swallowing exceptions without logging or reporting\n- Using exceptions for normal control flow (use `TryParse` instead)\n- Showing stack traces directly to end users",
   "id": "e88df8a9"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Practice\n\n1. Read a value from the console and keep prompting until a valid `double` is entered.\n2. Open a file path provided by the user; print a friendly message for: file not found, access denied, and unknown I/O error.\n3. Add argument checks to one of your existing methods and throw `ArgumentException` when input is invalid.",
   "id": "ca00b28a"
  },
  {
   "cell_type": "markdown",
   "id": "footnotes",
   "metadata": {},
   "source": "```{rubric} Footnotes\n```\n"
  }
 ]
}
