{
 "nbformat": 4,
 "nbformat_minor": 5,
 "metadata": {
  "kernelspec": {
   "display_name": "C#",
   "language": "csharp",
   "name": ".net-csharp"
  },
  "language_info": {
   "name": "csharp"
  }
 },
 "cells": [
  {
   "cell_type": "markdown",
   "id": "nul00",
   "metadata": {},
   "source": "# Nullable Types and Null Operators\n\n`null` is the source of countless runtime crashes. Modern C# (8+) provides tools to make null-handling explicit, safe, and concise.",
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "nul01",
   "metadata": {},
   "source": "## Nullable Value Types\n\nBy default, value types (`int`, `double`, `bool`) cannot be `null`. Append `?` to opt in:\n\n```csharp\nint  x = null;   // compile error\nint? y = null;   // OK\n```\n\nCheck before use with `.HasValue` / `.Value`, or use the null operators below.",
   "outputs": []
  },
  {
   "cell_type": "code",
   "id": "nul02",
   "metadata": {},
   "source": "int? score = null;\n\nif (score.HasValue)\n    Console.WriteLine($\"Score: {score.Value}\");\nelse\n    Console.WriteLine(\"No score yet.\");\n\n// Shorthand with null-coalescing\nint display = score ?? 0;\nConsole.WriteLine($\"Display: {display}\");  // Display: 0",
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "id": "nul03",
   "metadata": {},
   "source": "## Nullable Reference Types (C# 8+)\n\nEnable with `#nullable enable` (or project-wide via `<Nullable>enable</Nullable>`).\nOnce enabled, `string` means *non-nullable*; `string?` means *may be null*.\nThe compiler warns if you dereference a potentially-null reference.",
   "outputs": []
  },
  {
   "cell_type": "code",
   "id": "nul04",
   "metadata": {},
   "source": "#nullable enable\n\nstring  name = \"Alice\";   // cannot be null\nstring? nick = null;      // may be null\n\n// Console.WriteLine(nick.Length);  // warning: dereference of possibly null\nConsole.WriteLine(nick?.Length);  // OK \u2014 prints nothing if null",
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "id": "nul05",
   "metadata": {},
   "source": "## The Null Operators\n\n| Operator | Name | Meaning |\n|---|---|---|\n| `x ?? y` | Null-coalescing | Return `x` if not null, else `y` |\n| `x ??= y` | Null-coalescing assignment | Assign `y` to `x` only if `x` is null |\n| `x?.Member` | Null-conditional | Access `Member` only if `x` is not null |\n| `x?[i]` | Null-conditional index | Index only if `x` is not null |\n| `x!` | Null-forgiving | Suppress the nullable warning (use sparingly) |",
   "outputs": []
  },
  {
   "cell_type": "code",
   "id": "nul06",
   "metadata": {},
   "source": "// ?? \u2014 null-coalescing\nstring? input = null;\nstring result = input ?? \"(none)\";\nConsole.WriteLine(result);  // (none)\n\n// ??= \u2014 assign only if null\ninput ??= \"default\";\nConsole.WriteLine(input);  // default\n\n// ?. \u2014 null-conditional chain\nstring[]? words = null;\nint? len = words?.Length;\nConsole.WriteLine(len);  // (nothing printed \u2014 len is null)",
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "id": "nul07",
   "metadata": {},
   "source": "### Chaining `?.` and `??`\n\nCombine them for safe, concise access with a fallback.",
   "outputs": []
  },
  {
   "cell_type": "code",
   "id": "nul08",
   "metadata": {},
   "source": "record Order(string? CustomerName, Address? ShippingAddress);\nrecord Address(string City, string Zip);\n\nOrder? order = null;\n\n// Safe deep access with fallback\nstring city = order?.ShippingAddress?.City ?? \"Unknown\";\nConsole.WriteLine(city);  // Unknown",
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "id": "nul09",
   "metadata": {},
   "source": "## Pattern Matching and Null\n\nPattern matching integrates cleanly with nullability:\n\n```csharp\nstring? s = GetValue();\n\nstring result = s switch\n{\n    null              => \"(none)\",\n    { Length: 0 }    => \"(empty)\",\n    _                 => s\n};\n```",
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "nul10",
   "metadata": {},
   "source": "## Practice\n\n1. Write `int SafeParse(string? input)` that returns the parsed integer, or `0` if `input` is null or not a valid number. Use `int.TryParse`.\n2. Given `List<string?> names`, use LINQ and `??` to produce a `List<string>` where every null is replaced with `\"Anonymous\"`.\n3. Rewrite this safely using null operators:\n   ```csharp\n   if (user != null && user.Address != null)\n       Console.WriteLine(user.Address.City);\n   ```",
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "id": "nul11",
   "metadata": {},
   "source": "```{rubric} Footnotes\n```",
   "outputs": []
  }
 ]
}