# Projects, NuGet & Tooling - From Files to a Real Solution

So far you've been writing C# the way you learn it: a few `.cs` files, one `Main`, run it, see output. But the moment you build something real - more than a handful of files, someone else's code pulled in, or something you need to *ship* - you step into the **toolchain**: how C# code is grouped, packaged, and turned into something you can hand to a server or teammate.

The mental model worth holding onto: **a C# project is not a folder of files - it's a `.csproj` file that *describes* a folder of files.** That XML file is the source of truth: which .NET version you target, which packages you depend on, what kind of thing you're building. Once you see the `.csproj` as the center of gravity, the `dotnet` commands, NuGet, and the IDEs click into place around it.

## Namespaces & `using` - giving your types an address

📝 **Namespace.** A *named container* for your types - grouping related classes, structs, and enums under one label so full names don't collide. `string` lives in `System`; `JsonSerializer` lives in `System.Text.Json`. Think of it as a postal address: `System.Text.Json.JsonSerializer` is the full address, the namespace everything before the last dot.

Declare one with `namespace`; *import* one with `using` to refer to its types by short names instead of typing the full address every time.

```csharp
namespace MyApp.Billing;   // everything in this file lives here

public class Invoice
{
    public decimal Total { get; set; }
}
```

```csharp
// In another file:
using MyApp.Billing;       // import the namespace...
using System;

Invoice inv = new() { Total = 42.50m };   // ...so we can say "Invoice", not "MyApp.Billing.Invoice"
Console.WriteLine(inv.Total);             // "Console" comes from the "using System;"
```

*What just happened:* The first file put `Invoice` at the address `MyApp.Billing.Invoice`. The second said `using MyApp.Billing;`, telling the compiler "look in there too" - so `Invoice` resolves without the full prefix; otherwise you'd write `MyApp.Billing.Invoice` every time. Same for `using System;`, why `Console` works unqualified. (The `;` after the namespace name is the modern *file-scoped* form; the older `namespace MyApp.Billing { ... }` brace-block style means the same thing.)

💡 **Global & implicit usings - why your files look so bare.** Modern C# projects (.NET 6+) use two conveniences to stop repeating imports. A **global using**, written once, applies to the entire project: `global using System.Text.Json;` in any file means every file can use it. **Implicit usings** - one line in your `.csproj` - auto-add namespaces nearly every program needs (`System`, `System.Collections.Generic`, `System.Linq`). That's why a fresh file can call `Console.WriteLine` with *no* `using`: the project already imported `System` behind the scenes.

## Projects & solutions - the `.csproj` and the `.sln`

A loose pile of `.cs` files isn't a project. A **project** is defined by a `.csproj` file, and that's what `dotnet` actually compiles.

📝 **Project (`.csproj`).** A small XML file that *is* your project's definition: target framework, package dependencies, output type (executable vs. library). The `.cs` files in the same folder tree are pulled in automatically - one `.csproj` = one buildable unit.

📝 **Solution (`.sln`).** A *grouping* of multiple projects so you can open and build them together - a web app, a shared library, a test project, three `.csproj` files tied into one `.sln` your IDE opens. Small programs need no solution at all.

Here's a complete, tiny `.csproj` - notice how little is in it:

```xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>
```

*What just happened:* This is the entire project definition for a runnable app. `Sdk="Microsoft.NET.Sdk"` brings in the default build machinery. `<OutputType>Exe</OutputType>` says "build an executable" (drop this and you get a library `.dll`). `<TargetFramework>net10.0</TargetFramework>` pins the .NET version. `<ImplicitUsings>enable</ImplicitUsings>` is the auto-import switch from above; `<Nullable>enable</Nullable>` turns on the nullable-reference warnings from Phase 9. No source file list - every `.cs` under this folder is included by convention.

You don't hand-write these. The `dotnet` CLI scaffolds, builds, and runs them:

```bash
dotnet new console -o HelloApp   # scaffold a new console project in ./HelloApp
cd HelloApp
dotnet run                       # compile and run in one step
dotnet build                     # compile only, produce the binaries
```

*What just happened:* `dotnet new console` generated a folder with a ready-to-go `.csproj` and a starter `Program.cs`. `dotnet run` is your fast inner loop - compiles and immediately runs, like "F5" from the command line. `dotnet build` compiles but stops there. (`dotnet new` has many templates - `classlib`, `web`, `xunit` - each scaffolding the right `.csproj`.)

## NuGet - the package manager you'll lean on constantly

You will not write everything yourself, and shouldn't try. **NuGet** gets you the .NET world's vast catalog of ready-made libraries.

📝 **NuGet.** The .NET package manager. A *package* is a bundle of compiled, reusable code (plus metadata) published to a registry - the public one is **nuget.org**. Add a package and your code can use it. The .NET equivalent of npm or pip.

Adding one is a single command:

```bash
dotnet add package Newtonsoft.Json
```

```console
info : Adding PackageReference for package 'Newtonsoft.Json' into project '...HelloApp.csproj'.
info : Restoring packages for ...HelloApp.csproj...
info : Installed Newtonsoft.Json 13.0.3 from https://api.nuget.org/v3/index.json
```

*What just happened:* `dotnet add package` looked up `Newtonsoft.Json` on nuget.org, picked the latest stable version, downloaded it, and - the key part - *recorded the dependency in your `.csproj`*. No files were manually copied. Next build, .NET **restores** it automatically (downloads if not cached), so a teammate who clones your repo just runs `dotnet build` and the package shows up too.

That recorded dependency looks like this inside the `.csproj`:

```xml
<ItemGroup>
  <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
```

*What just happened:* `<PackageReference>` says "this project depends on this package at this version" - all `dotnet add package` did. Living in version-controlled XML, not copied binaries, keeps your repo small and versions reproducible from the `.csproj` alone.

💡 **Reach for a package before rolling your own.** JSON parsing, HTTP clients with retries, date/time handling, CSV, PDFs, database access - the odds someone's already built and battle-tested what you need are high. Search nuget.org first; a mature package has handled edge cases you haven't thought of, and "I added a well-maintained package" beats "I wrote my own and now maintain it forever."

## Build & publish - compile vs. ship

`dotnet build` and `dotnet publish` sound similar and are easy to mix up. The difference: *who the output is for*.

📝 **Build vs. publish.** `dotnet build` compiles for *you* to run and debug locally. `dotnet publish` produces a *deployable* bundle - everything needed on another machine, ready for a server or container.

```bash
dotnet build                                   # compile for local use
dotnet publish -c Release -o ./out             # produce a deployable bundle
```

*What just happened:* `dotnet build` produced binaries under `bin/`, ready to run on your dev machine where the runtime's already installed. `dotnet publish -c Release` did an optimized compile and gathered the result into `./out` - a shippable folder. Publish comes in two flavors: **framework-dependent** (smaller, but the target needs the matching runtime installed) and **self-contained** (larger, bundles the runtime, so the target needs nothing pre-installed) - what makes "copy this folder to a bare server and run it" possible.

⚠️ **The `bin/` and `obj/` folders - generated, never committed.** Every build creates `obj/` (intermediate compiler junk) and `bin/` (final binaries). Both are *generated output*, rebuilt from source any time, so they don't belong in version control. The default `.gitignore` already excludes them; committing them is a classic beginner mistake that bloats the repo and causes merge conflicts over files nobody edits.

## The wider toolchain - the batteries that come with C#

The `dotnet` CLI is the engine, but you'll spend your days inside richer tools built around it:

- **IDEs & editors.** **Visual Studio** (Windows-only, full-featured heavyweight), **VS Code** with the **C# Dev Kit** extension (lightweight, cross-platform, hugely popular), and **JetBrains Rider** (cross-platform, beloved for refactoring; the usual pick on Mac and Linux). All three give IntelliSense, a visual debugger, and one-click run/test - all driving the same `dotnet` build.
- **`dotnet format`.** The built-in formatter. Like `gofmt` or `black`, it enforces consistent whitespace so code review stops being about indentation. Run before committing, or wire it to run on save.
- **Analyzers & Roslyn.** C#'s compiler is **Roslyn**, exposing its understanding of your code to *analyzers* - plugins flagging bugs, style violations, and risky patterns *as you type*. Many ship with the SDK automatically; teams add more for their own rules.
- **Testing & profiling.** Unit testing (**xUnit** and friends) and profiling are first-class here, big enough for their own treatment in Phase 16. For now, know `dotnet test` exists.

💡 **Key point.** C# has one of the most *batteries-included*, mature toolchains in software. Build tool, package manager, formatter, analyzers, and test runner are all official, integrated, and driven by the same `dotnet` CLI - not third-party parts hoped to cooperate.

## Recap

1. **Namespaces** give types an address (`namespace MyApp;`) and **`using`** imports them so you can use short names; **global/implicit usings** mean modern files often need no imports at all.
2. **A `.csproj` *is* the project** - a small XML file naming the target framework, output type, and `<PackageReference>` dependencies; the `.cs` files come in by convention. A **`.sln`** groups multiple projects.
3. **`dotnet new` / `build` / `run`** scaffold, compile, and run; **NuGet** (`dotnet add package`) pulls in outside libraries from nuget.org, recording them in the `.csproj` so they restore automatically.
4. **`dotnet build`** compiles for local use; **`dotnet publish`** produces a deployable bundle (framework-dependent or self-contained). The generated **`bin/`** and **`obj/`** folders never get committed.
5. The wider toolchain - **Visual Studio / VS Code + C# Dev Kit / Rider**, **`dotnet format`**, **Roslyn analyzers**, and the testing/profiling tools coming in Phase 16 - is mature, official, and integrated around the same `dotnet` CLI.

You can now organize, package, and ship real C# - not just run loose files. Next we cover the idioms and gotchas that separate "compiles" from "looks like C# a pro would write."

## Quick check

Make sure the core mental model - the `.csproj` as the center of a project - stuck:

```quiz
[
  {
    "q": "What does a `.csproj` file actually define?",
    "choices": [
      "The project itself: its target framework, output type, and package dependencies - the .cs files are included by convention",
      "A list of every source file in the project, which you must keep up to date by hand",
      "Only the compiled output binaries, regenerated on each build",
      "The solution that groups several projects together"
    ],
    "answer": 0,
    "explain": "The `.csproj` is the project's definition - target framework, output type, and `<PackageReference>` dependencies. The `.cs` files under its folder are pulled in automatically, so you don't list them. Grouping multiple projects is the job of a `.sln`."
  },
  {
    "q": "After you run `dotnet add package Newtonsoft.Json`, how does the package end up available to a teammate who clones your repo?",
    "choices": [
      "The command records a `<PackageReference>` in the .csproj, and `dotnet build` restores the package automatically from it",
      "The package's binaries are copied into the repo and committed alongside your code",
      "Your teammate must manually download the package from nuget.org and place it in bin/",
      "The package is embedded directly into every .cs file that uses it"
    ],
    "answer": 0,
    "explain": "`dotnet add package` edits a `<PackageReference>` line into the `.csproj`. Because the dependency lives in version-controlled XML, a fresh clone just needs `dotnet build`, which restores (downloads) the recorded packages automatically - no binaries committed to the repo."
  },
  {
    "q": "What's the difference between `dotnet build` and `dotnet publish`?",
    "choices": [
      "`build` compiles binaries for you to run locally; `publish` produces a deployable bundle (optionally self-contained) for another machine",
      "`build` is for libraries and `publish` is for executables",
      "They are identical; `publish` is just the older name for `build`",
      "`build` downloads NuGet packages while `publish` removes them"
    ],
    "answer": 0,
    "explain": "`dotnet build` compiles binaries for local running and debugging. `dotnet publish` gathers everything needed to deploy elsewhere - framework-dependent (needs the runtime installed) or self-contained (bundles the runtime so the target needs nothing)."
  }
]
```
