{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a2551e40-f1e9-4120-a40f-bb4cf31d65e5",
   "metadata": {},
   "source": [
    "```{index} program structure\n",
    "```\n",
    "\n",
    "(program-structure)=\n",
    "\n",
    "# C# Program Structure\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b3272868",
   "metadata": {},
   "source": [
    "## The .NET Templates\n",
    "\n",
    "The .NET SDK comes with built-in templates for creating projects and files, including console apps,\n",
    "class libraries, unit test projects, etc. For learning purposes, we will mainly use the console app\n",
    "template. To see the list of templates, you may issue the `dotnet new list` command:\n",
    "\n",
    "```{code-block} powershell\n",
    ":emphasize-lines: 1, 13\n",
    "PS C:\\> dotnet new list\n",
    "These templates matched your input:\n",
    "\n",
    "Template Name                       Short Name      Language    Tags \n",
    "----------------------------------  --------------  ----------  ------------------------\n",
    "API Controller                      apicontroller   [C#]        Web/ASP.NET \n",
    "ASP.NET Core Empty                  web             [C#],F#     Web/Empty \n",
    "ASP.NET Core Web API                webapi          [C#],F#     Web/Web API/API/Service \n",
    "...\n",
    "ASP.NET Core Web App (Razor Pages)  webapp,razor    [C#],F#     Web/MVC/Razor Pages \n",
    "Blazor Web App                      blazor          [C#]        Web/Blazor/WebAssembly \n",
    "Class Library                       classlib        [C#],F#,VB  Common/Library \n",
    "Console App                         console         [C#],F#,VB  Common/Console \n",
    "...\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8431f40a",
   "metadata": {},
   "source": [
    "## A Console App\n",
    "\n",
    "We can try out the Console App template, which will give us a \"Hello, World\" message\n",
    "when executing. In the terminal, let us\n",
    "change directory (`cd`) into the test directory and issue command `dotnet new console`.\n",
    "The .NET SDK will generate a project for us, which will include the following files and\n",
    "directories:\n",
    "\n",
    "1.  The `Program.cs` file\n",
    "2.  The `obj` folder\n",
    "3.  The `testPrj.csproj` file\n",
    "4.  Also, a `bin` directory will be created later after the project is built.\n",
    "\n",
    "```{code-block} powershell\n",
    ":emphasize-lines: 1, 2, 10\n",
    "\n",
    "PS C:\\[username]> cd test\n",
    "PS C:\\[username]\\test> dotnet new console\n",
    "The template \"Console App\" was created successfully.\n",
    "\n",
    "Processing post-creation actions...\n",
    "Restoring C:\\Users\\[username]\\test\\test.csproj:\n",
    "Restore succeeded.\n",
    "\n",
    "\n",
    "PS C:\\Users\\[username]\\test> ls\n",
    "    Directory: C:\\Users\\[username]\\test\n",
    "\n",
    "Mode                 LastWriteTime         Length Name\n",
    "----                 -------------         ------ ----\n",
    "d-----         3/12/2026  12:40 PM                obj\n",
    "-a----         3/12/2026  12:40 PM             40 Program.cs\n",
    "-a----         3/12/2026  12:40 PM            253 test.csproj\n",
    "\n",
    "PS C:\\Users\\[username]\\test>\n",
    "```\n",
    "\n",
    "From the terminal we can open vscode by typing `code .` and hit Enter (the dot `.` means the current directory; namely, open VS Code and use this current directory as project folder).\n",
    "\n",
    "```console\n",
    "PS C:\\Users\\tcn85\\test> code .\n",
    "PS C:\\Users\\tcn85\\test>\n",
    "```\n",
    "\n",
    "VS Code will open. We then choose the Explorer (<i class=\"far fa-copy\"></i>) view and click on the Program.cs file. You will see that the Program.cs looks\n",
    "simple as below and we are working the executable code directly.\n",
    "\n",
    "```{code-block} c#\n",
    ":linenos: true\n",
    "\n",
    "Console.WriteLine(\"Hello, World!\");\n",
    "```\n",
    "\n",
    "The template is very succinct because of after C#9 there's a feature called **top-level statements**, with which you write and execute code without the boilerplate `class` and `Main` method wrapper because he compiler automatically generates a Program class with an entry point method for the application and adds a set of implicit `global using` directives such as Microsoft.NET.Sdk to include the most common namespaces.\n",
    "\n",
    "While top-level statements are friendly to new users and is the default when you create a new project using `dotnet new console`, there's a limit that only one file in a project can have top-level statements. Therefore, as we learn more about C# programming, you will need to learn how to structure your code using namespaces and classes.\n",
    "\n",
    "```{important}\n",
    "**There can be only one entry point (the `Main()` method) per C# project, but a project can have many `.cs` files.**\n",
    "\n",
    "A `.csproj` file defines a project, and a project can only have **one entry point** — either one file with top-level statements, or one `static void Main()` method. However, a project can contain as many `.cs` files as you like; all extra `.cs` files just define additional classes or helpers that the entry point can use. If you have two programs that each need their own `Main()`, they must be **two separate projects** (two separate `.csproj` files).\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1970f9d",
   "metadata": {},
   "source": [
    "## C# Program Structure\n",
    "\n",
    "### Creating a C# Project\n",
    "To use the conventional C# program style, you use the `--use-program-main` option to create a console app project with the `Main` method. In the example below, we create a test2 folder, change into the test2 folder, then issue `dotnet new console` with the option `--use-program-main` to create the project with conventional `Program.cs` structure:\n",
    "\n",
    "```powershell\n",
    "PS C:\\Users\\[username]> mkdir test2\n",
    "    Directory: C:\\Users\\[username]\n",
    "Mode                 LastWriteTime         Length Name\n",
    "----                 -------------         ------ ----\n",
    "d-----         3/13/2026  12:12 AM                test2\n",
    "\n",
    "PS C:\\Users\\[username]> cd test2\n",
    "PS C:\\Users\\[username]\\test2> dotnet new console --use-program-main\n",
    "The template \"Console App\" was created successfully.\n",
    "\n",
    "Processing post-creation actions...\n",
    "Restoring C:\\Users\\[username]\\test2\\test2.csproj:\n",
    "Restore succeeded.\n",
    "\n",
    "After creating the project, we first `ls` (list) the folder to see what files and directories are there.\n",
    "\n",
    "```powershell\n",
    "PS C:\\Users\\[username]\\test2> ls\n",
    "    Directory: C:\\Users\\[username]\\test2\n",
    "Mode                 LastWriteTime         Length Name\n",
    "----                 -------------         ------ ----\n",
    "d-----         3/13/2026  12:12 AM                obj\n",
    "-a----         3/13/2026  12:12 AM            140 Program.cs\n",
    "-a----         3/13/2026  12:12 AM            253 test2.csproj\n",
    "```\n",
    "\n",
    "This will give us the same project files as running `dotnet new console` without the `--use-program-main` option, but the `Program.cs` file will be different. Opening the `Program.cs` and you see the template code as:\n",
    "\n",
    "```csharp\n",
    "namespace testPrj;\n",
    "\n",
    "class Program\n",
    "{\n",
    "    static void Main(string[] args)\n",
    "    {\n",
    "        Console.WriteLine(\"Hello, World!\");\n",
    "    }\n",
    "}\n",
    "```\n",
    "\n",
    "The boilerplate code above actually means we formally wrap our C# code around in layers when our project scale go beyond a simple script:\n",
    "\n",
    "```text\n",
    "┌─────────────────────────────────────────┐\n",
    "│  namespace testPrj                      │\n",
    "│  ┌───────────────────────────────────┐  │\n",
    "│  │  class Program                    │  │\n",
    "│  │  ┌─────────────────────────────┐  │  │\n",
    "│  │  │  static void Main(string[]) │  │  │\n",
    "│  │  │  {                          │  │  │\n",
    "│  │  │      // statements here     │  │  │\n",
    "│  │  │  }                          │  │  │\n",
    "│  │  └─────────────────────────────┘  │  │\n",
    "│  └───────────────────────────────────┘  │\n",
    "└─────────────────────────────────────────┘\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6519dc54",
   "metadata": {},
   "source": [
    "### The Program.cs\n",
    "\n",
    "Some important concepts that you need to learn from this template code example here so we have better ideas about the basic structure of C# programs.\n",
    "\n",
    "(using System)=\n",
    "1. `using System;`:\n",
    "\n",
    "   Starting .NET 6, `using System` is implicit as defined in the `.csproj` file so it is not shown in the Program.cs file. We should know that, `System` is a root-level **namespace** that contains basic defined value and reference types. The `using` directive allows you to use the types defined in a namespace without specifying the fully qualified namespace of that type. For example, `Console` is a class inside the\n",
    "   `System` namespace and we use its `WriteLine` method to print to the console by typing `Console.WriteLine()`, less the `System` part.\n",
    "\n",
    "   ```csharp\n",
    "   using System;\n",
    "   Console.WriteLine(\"Hello\");  // instead of System.Console.WriteLine\n",
    "   ```\n",
    "\n",
    "(namespace)=\n",
    "\n",
    "2.  **`namespace`**:\n",
    "    The `namespace` keyword is used to declare a scope to organize types (such as classes). For example, following the template's program structure, we may define a namespace as below to contain unique code elements such as class, interface, struct, which will be implemented to create functionalities for the application.\n",
    "\n",
    "    ```csharp\n",
    "        namespace SampleNamespace\n",
    "        {\n",
    "            class SampleClass { }\n",
    "            interface ISampleInterface { }\n",
    "            struct SampleStruct { }\n",
    "            enum SampleEnum { a, b }\n",
    "            delegate void SampleDelegate(int i);\n",
    "            namespace Nested\n",
    "            {\n",
    "                class SampleClass2 { }\n",
    "            }\n",
    "        }\n",
    "    ```\n",
    "\n",
    "    An example of namespace is the `System` namespace in .NET, which defines some of the fundamental types. When we run\n",
    "    `Console.WriteLine(\"Hello, World\");`, we are actually running\n",
    "    `System.Console.WriteLine(\"Hello World!\");` We do not specify “System” because it is “imported” (by the hidden `using System`) already and we can use the fundamental features (e.g., `Console`, `String`, `Math`, etc) within the namespace. Software engineers use namespace the same way to organize the functionalities in applications. [^1]\n",
    "\n",
    "3.  **`class`**:\n",
    "    A class is a blueprint for creating objects. It is a user-defined reference type that defines:\n",
    "\n",
    "    - **fields/properties** (data that describe the object), and\n",
    "    - **methods** (functions that define the object's behavior).\n",
    "\n",
    "    By convention, each class is defined in its own file, named after the class (e.g., MyClass.cs).\n",
    "\n",
    "4.  The **`Main`** method:\n",
    "    The **Main method** is the **entry point** of a C# application and therefore\n",
    "    the first method invoked when an application is executed. There is only one\n",
    "    entry point in a C# program.\n",
    "\n",
    "5.  `method`:\n",
    "    A method (function) is an object-oriented term for function, which is a series\n",
    "    of statements designed to perform certain task. In C#, just like Java, the\n",
    "    *Main method* is the entry point of the program, meaning it is the first\n",
    "    method invoked when a program is executed.\n",
    "\n",
    "6.  `static` & `void`:\n",
    "\n",
    "    - The modifier `static` means the method can be called without creating\n",
    "      a new object from the class.\n",
    "    - `void` means the Main method does not return anything.\n",
    "\n",
    "7.  `string[] args`:\n",
    "    The `args` are called “command line arguments” and in this example the type is\n",
    "    string array; meaning when calling this method you send the arguments in and they are zero-indexed as an array."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "source": [
    "### Top-Level Statements\n",
    "\n",
    "When you create a real console project with `dotnet new console` (without the option `--use-program-main`), the generated `Program.cs` uses **top-level statements** (the default since .NET 6), which lets you write code without explicitly declaring `class Program` and `Main`. You still create a project and it still compiles into a proper executable, but the compiler automatically wraps the top-level statements into an entry point, which is equivalent to the explicit `class Program` / `static void Main`. As you might have noticed, the `Program.cs` \n",
    "\n",
    "```powershell\n",
    "// See https://aka.ms/new-console-template for more information\n",
    "Console.WriteLine(\"Hello, World!\");\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8364217e",
   "metadata": {},
   "source": [
    "### Script Mode\n",
    "\n",
    "When you enable the **Live Code** mode of the page, you can write and run C# inside the code cells (but not markdown cells), the .NET Interactive kernel, similar to **`csharprepl`**, runs code in **script mode**: you write statements directly without creating a project wrapping code in a `namespace`, `class`, or `Main` method. This is similar to how Python or JavaScript work in their REPL.\n",
    "\n",
    "\n",
    "| | Script mode (notebook) | Top-level statements (project) | Explicit `Main` (project) |\n",
    "|---|---|---|---|\n",
    "| `namespace` declaration | not supported | optional | optional |\n",
    "| `class Program` / `Main` | can do but not needed | can do but not needed |  required |\n",
    "| Compiles to `.exe` | interpreted/runs in-memory | supported | supported |\n",
    "| How to create | .NET Interactive notebooks | `dotnet new console` (default) | `dotnet new console --use-program-main` |\n",
    "\n",
    "In this book, notebooks use **script mode** for interactive exploration, while the companion C# projects use **top-level statements** or the explicit `Main` form depending on context."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f76b334",
   "metadata": {},
   "source": [
    "## Solutions and Projects\n",
    "\n",
    "For simple project, you can create a project without creating a solution. To do that, create a directory in command line, and issue the command such as `dotnet new console --use-program-main` to use the .NET templates for creating new projects. A `.csproj` file will be created and you know that this is a project folder.\n",
    "\n",
    "For more complicated projects, the .NET platform uses **solutions** and **projects** to organize code items in specific structure. A solution is a **container** or **workspace** for one or more projects, and each project would contain source code files. A web app solution, for example, may include a website project, a database project, and a server-side API project; and each of the project will be named differently under different project folders inside the solution directory."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18262b29",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "source": [
    "\n",
    "```text\n",
    "┌────────────────────────────────────────────────────────────────────┐\n",
    "│                            MySolution.sln                          │\n",
    "│                   Solution file – groups all projects              │\n",
    "│                                                                    │\n",
    "│ ┌────────────────┐  ref  ┌────────────────┐ ref ┌────────────────┐ │\n",
    "│ │  MyApp.API     │ ────▶ │  MyApp.Core    │◀────│  MyApp.Infra   │ │\n",
    "│ │                │       │                │     │                │ │\n",
    "│ │ .csproj        │       │ .csproj        │     │ .csproj        │ │\n",
    "│ │ Controllers,   │       │ Models,        │     │ DB,            │ │\n",
    "│ │ endpoints      │       │ interfaces     │     │ repositories   │ │\n",
    "│ └────────────────┘       └───────▲────────┘     └────────────────┘ │\n",
    "│                               ref│                                 │\n",
    "│                         ┌────────┴───────┐                         │\n",
    "│                         │  MyApp.Tests   │                         │\n",
    "│                         │                │                         │\n",
    "│                         │ .csproj        │                         │\n",
    "│                         │ Unit &         │                         │\n",
    "│                         │ integration    │                         │\n",
    "│                         │ tests          │                         │\n",
    "│                         └────────────────┘                         │\n",
    "└────────────────────────────────────────────────────────────────────┘\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db856810",
   "metadata": {},
   "source": [
    "To create a solution as a workspace, we use the command `dotnet new sln` in the solution directory. You then create all your project directories in the solution directory, and then create a new project in each of the project directories using the .NET templates (e.g., Console App or Web App). "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d02603ea",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "source": [
    "```text\n",
    "MySolution/\n",
    "├── MySolution.sln\n",
    "├── MyApp/\n",
    "│   └── MyApp.csproj\n",
    "├── MyLibrary/\n",
    "│   └── MyLibrary.csproj\n",
    "└── MyTests/\n",
    "    └── MyTests.csproj\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b20fced4",
   "metadata": {},
   "source": [
    "To manage your projects and solutions, you can:\n",
    "\n",
    "1. Create a new solution\n",
    "\n",
    "    ```bash\n",
    "    dotnet new sln -n MySolution\n",
    "    ```\n",
    "\n",
    "2. Create a project\n",
    "    ```bash\n",
    "    dotnet new console -n MyApp\n",
    "    dotnet new classlib -n MyLibrary\n",
    "    ```\n",
    "\n",
    "3. **Add projects to the solution**\n",
    "    ```bash\n",
    "    dotnet sln MySolution.sln add MyApp/MyApp.csproj\n",
    "    dotnet sln MySolution.sln add MyLibrary/MyLibrary.csproj\n",
    "    ```\n",
    "\n",
    "4. Common solution commands for further management of projects and solutions include: \n",
    "\n",
    "<div style=\"width: fit-content; margin-left: 2rem;\">\n",
    "\n",
    "| Task | Command |\n",
    "|---|---|\n",
    "| List projects in solution | `dotnet sln list` |\n",
    "| Remove a project | `dotnet sln remove MyApp/MyApp.csproj` |\n",
    "| Add project reference | `dotnet add MyApp reference MyLibrary` |\n",
    "| Build entire solution | `dotnet build MySolution.sln` |\n",
    "| Run a specific project | `dotnet run --project MyApp` |\n",
    "| Add a NuGet package | `dotnet add MyApp package Newtonsoft.Json` |\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "26738794",
   "metadata": {},
   "source": [
    "If you create a project in a folder using VS Code’s “Create .NET Project” button in the Explorer view, a solution will be created with the same name as the project. To manage solutions, the Solution Explorer in VS Code can be used, with the **C# Dev Kit** extension installed. The Solution Explorer panel in the sidebar allows you to:\n",
    "- Add/remove projects\n",
    "- Manage NuGet packages\n",
    "- View project references\n",
    "- Run/debug projects\n",
    "[^2]."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f13e6049",
   "metadata": {},
   "source": [
    "## Comments, Curly Braces, and Semicolon\n",
    "\n",
    "Comments are important as they make code more readable. C# offers single-line and multiple-line\n",
    "comments:\n",
    "\n",
    "**Single-line Comments**: Single-line comments start with two forward slashes (//). Any text between // and the end of the line is ignored by C# (will not be executed).\n",
    "\n",
    "**Multi-line Comments**: Multi-line comments start with /\\* and ends with \\*/. Any text between /\\* and \\*/ will be ignored by C#.\n",
    "\n",
    "The **curly braces { }** in C# mark the beginning and the end of a block of code.\n",
    "\n",
    "**Semicolons** work as statement terminator character in C# and are required because they prevent syntax ambiguities.\n",
    "Semicolons after method or accessor block, however, is not allowed."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "723e5d6f",
   "metadata": {},
   "source": [
    "### Compound Statements (Code Blocks)\n",
    "\n",
    "A code block (or simply “block”), also referred to as a compound statement, is the grouping of multiple statements into a\n",
    "single statement. While each statement that ends with a semicolon, often it makes sense to see a block of\n",
    "statements as one lexical unit. In C#, a code block is delimited by a pair of curly braces to include\n",
    "a list of statements. For example, the following code shows an if statement, you can see the two highlighted\n",
    "code blocks being compound statements because the statements inside the curly braces. More specifically,\n",
    "line 4-9 is a compound statement of the if statement."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "282b6e2a",
   "metadata": {
    "language_info": {
     "name": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The area of the circle is: 78.54\n"
     ]
    }
   ],
   "source": [
    "double radius = 5.0;  // try a negative value to test the else branch\n",
    "double area;\n",
    "if (radius >= 0)\n",
    "{\n",
    "    // calculate the area of the circle\n",
    "    area = Math.PI * radius * radius;\n",
    "    Console.WriteLine($\"The area of the circle is: {area:0.00}\");\n",
    "}\n",
    "else\n",
    "{\n",
    "    Console.WriteLine($\"{radius} is not a valid radius.\");\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a20bb05",
   "metadata": {},
   "source": [
    "```{rubric} Footnotes\n",
    "```\n",
    "\n",
    "[^1]: To learn more about the .NET System namespace, see the .NET API documentation at <https://learn.microsoft.com/en-us/dotnet/api/system?view=net-8.0>.\n",
    "\n",
    "[^2]: To manage .NET solutions and projects, see, for example, <https://www.linkedin.com/pulse/managing-net-solution-files-dotnet-sln-sukhpinder-singh-arqvc/>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "name": "polyglot-notebook"
  },
  "polyglot_notebook": {
   "kernelInfo": {
    "defaultKernelName": "csharp",
    "items": [
     {
      "aliases": [],
      "name": "csharp"
     }
    ]
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
