Skip to main content
ANVISoftware Solutions
Lesson 1 of 12Intermediate16 min

What Is .NET?

By the end of this lesson

Describe what the platform provides beyond the language itself.

You can write C# for months without thinking about .NET. The editor builds, the program runs, and the platform stays out of the way. That works until something breaks outside your code: a server refuses to start your application, a package will not install, a setting is read from somewhere you did not expect.

.NET is four things bundled under one name: a runtime that executes compiled code, a large library of ready-made types, a toolchain that builds and packages projects, and a set of application services that most programs need regardless of what they do.

The fourth item is the one most descriptions skip, and it is the one that changes how you write code. Configuration, logging, dependency injection and hosting are part of the platform. You are not expected to build them.

The four parts, and where you meet each one:

The runtime
Loads your compiled code, translates it into machine instructions for the processor it finds, manages memory, and collects objects you no longer reference. You meet it when an application will not start, or when memory behaviour surprises you.
The base class library
Types shipped with the platform: collections, strings, dates, file access, an HTTP client, JSON reading and writing, threading, cryptography. Most lines you write call into it. It is often shortened to BCL.
The toolchain
The compiler, the build engine, the package client and the dotnet command. This is what turns a folder of .cs files into something deployable, and it is what a build pipeline drives.
Application services
Layered configuration, structured logging, a dependency injection container, and a host that starts and stops long-running work. Supplied as libraries you opt into, and the rest of this course covers them one at a time.

Cross-platform is the claim made most often about .NET, so it is worth being concrete about what it means. The compiler does not produce machine code. It produces intermediate language, a portable instruction set that means nothing to a processor. The runtime reads that and generates real machine instructions when the code is first called.

That is why one compiled assembly runs on Windows, Linux and macOS. The assembly is the same file; the runtime that loads it is built for the operating system and processor underneath. A Linux container running your API and a Windows laptop running the same tests execute the same intermediate language.

The parts that do differ are the ones that touch the machine: file path separators, case sensitivity of file names, available certificate stores, and anything you shell out to. A build that works on your laptop and fails in a Linux container is almost always tripping over one of those, not over the language.

What you get without writing it. Each of these is something teams used to build in-house, and each has its own lesson later in this course:

  • Settings read from files, environment variables and the command line, merged in a defined order
  • An environment name that lets one build behave differently in development and production
  • A container that constructs your classes and supplies what their constructors ask for
  • Logging with levels and named fields, writing to whatever destination you configure
  • A host that starts services in order, runs until told to stop, and then stops them cleanly
  • HTTP clients, JSON serialisation, health reporting and a test runner, all from the same toolchain
Program.cs — configuration, dependency injection and logging in one place
C#
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

var builder = Host.CreateApplicationBuilder(args);

// Settings, already merged from files, environment variables and the command line
int pageSize = builder.Configuration.GetValue<int>("Employees:PageSize");

// One place that knows how to construct things
builder.Services.AddSingleton<IEmployeeStore, InMemoryEmployeeStore>();

using IHost host = builder.Build();

ILogger<Program> logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Employees service starting with page size {PageSize}", pageSize);

await host.RunAsync();
  • Host.CreateApplicationBuilder does the setup work: it reads the environment name, adds the standard configuration sources in order, creates a logging factory, and creates an empty service collection.
  • builder.Configuration is a merged view of every source. You ask for a key; you do not care which file or variable it came from.
  • builder.Services is the registration list. Nothing is constructed here — you are recording how to build an IEmployeeStore when something asks for one.
  • builder.Build() freezes both of those and produces the host. After this point the registration list is closed.
  • The log call passes PageSize as a named field rather than pasting it into a sentence, which is what makes it searchable later. The logging lesson goes into why that matters.
  • RunAsync starts every registered background service and waits. It returns when the process is asked to stop, which the lifecycle lesson covers in detail.

Summary

  • .NET is a runtime, a base class library, a toolchain and a set of application services
  • The compiler emits portable intermediate language; the runtime turns it into machine instructions on the machine it runs on
  • Configuration, logging, dependency injection and hosting come with the platform and are not web-specific
  • The included pieces cost you conventions to learn, extra startup machinery, and some failures that surface at run time rather than compile time
  • .NET Framework is the older Windows-only line — check which one a search result is describing

Practice

Attempt each one before opening the solution. Getting it wrong first is how the idea sticks.

Think about it

Which parts is this program re-implementing?

A colleague has a console tool that imports employee records from a CSV file. It reads its database connection string with File.ReadAllText from a settings.txt file next to the executable, writes progress with Console.WriteLine, and calls new SqlConnection(...) directly inside three different classes.

Name the platform features each of those three habits replaces, and state one genuine cost of moving the tool over.

Show solution

Reading settings.txt by hand replaces configuration. The platform version reads the same value from a file, an environment variable or the command line without the tool knowing which, so the same build works on a laptop and in a container.

Console.WriteLine replaces logging. The difference is not where the text appears, it is that a log entry has a level, a category and named fields, so it can be filtered and searched. Console output is one string with none of that.

Constructing SqlConnection in three classes replaces dependency injection. Each class decides for itself how to reach the database, so changing that decision means editing three files, and testing any of them requires a real database.

The honest cost: the tool grows a host, a builder and a handful of registrations before it does anything useful, and a mistake in that setup shows up at run time rather than at compile time. For a script that runs once, that overhead may not be worth paying. For a tool that runs nightly and needs to be diagnosed when it fails, it is.

Try it yourself

Run the smallest host you can

Create a console project, add the Microsoft.Extensions.Hosting package, and get the sample above running. Replace the IEmployeeStore registration with anything you like, or delete it for now.

Then add an appsettings.json file containing an Employees section with a PageSize of 50, and set the same key as an environment variable with a different value. Run it both ways and see which value the log line reports.

Show solution

The environment variable wins. Later configuration sources override earlier ones, and environment variables are added after the JSON files. The configuration lesson sets out the full order.

If your appsettings.json appears to be ignored entirely, check the bin folder. A plain console project does not copy that file to the output directory unless the project file says to, which catches people who expect the behaviour they have seen in web projects.

Shell
dotnet new console -o Anvi.Employees.Tool
cd Anvi.Employees.Tool
dotnet add package Microsoft.Extensions.Hosting
dotnet run

Saved in this browser only.