C#
Modern, productive and runs everywhere with .NET.
C# is Microsoft's flagship language for .NET. It powers web back ends, Windows and cross-platform apps, Unity games and Azure services, and Microsoft's Semantic Kernel brings LLM agents to it.
Why learn C#?
C# combines strong typing with modern features like async/await, LINQ and records, plus excellent tooling in Visual Studio and VS Code.
- Versatile: web, desktop, mobile, games and cloud with one language.
- Unity: the most popular engine for indie and mobile games.
- AI: Semantic Kernel, ML.NET and ONNX Runtime integrate AI into .NET apps.
Set up and run your first program
Install the .NET 8 SDK or newer, then create a console app.
dotnet --version
dotnet new console -o HelloAi
cd HelloAi && dotnet runvar name = "Ada";
Console.WriteLine($"Hello, AI! Welcome to C#, {name}.");Program.cs needs no class or Main method.Variables and types
Use var for inferred types or name the type. Strings support interpolation with $"...{x}". Nullable types end in ?.
int layers = 32;
double lr = 3e-4;
var model = "llama3.1";
long parameters = 8_030_000_000;
string? note = null; // may be null
Console.WriteLine($"{model}: {layers} layers, FP16 {parameters * 2 / 1e9:F1} GB, note={note ?? "none"}");Control flow and pattern matching
Loops include for, foreach and while. switch expressions and patterns make branching concise.
foreach (var gpu in new[] { "H100", "B200" }) Console.WriteLine(gpu);
int bits = 8;
string name = bits switch {
32 => "FP32",
16 => "FP16",
8 => "FP8",
_ => "other"
};
Console.WriteLine(name);Classes and records
Classes hold state and behaviour. record types are immutable data with value equality, ideal for messages and DTOs.
record Gpu(string Name, int VramGb)
{
public bool Fits(double modelGb) => modelGb <= VramGb;
}
var g = new Gpu("RTX 5090", 32);
Console.WriteLine($"{g} fits 16 GB: {g.Fits(16)}");Collections and LINQ
List<T> and Dictionary<K,V> are the main collections. LINQ queries filter, sort and project data in one readable chain.
var vram = new Dictionary<string, int> { ["H100"] = 80, ["H200"] = 141, ["B200"] = 180 };
var big = vram.Where(kv => kv.Value > 100).OrderBy(kv => kv.Key).Select(kv => kv.Key);
Console.WriteLine(string.Join(", ", big)); // B200, H200Async and await
I/O-bound work like HTTP calls uses async/await so threads are not blocked. HttpClient is the standard HTTP client.
using var http = new HttpClient();
try {
string json = await http.GetStringAsync("http://localhost:11434/api/tags");
Console.WriteLine(json[..Math.Min(120, json.Length)]);
} catch (HttpRequestException e) {
Console.WriteLine($"Is Ollama running? {e.Message}");
}AI with C#
C# is a strong choice for adding AI to business apps: chat features, document Q&A and agents inside .NET services. ML.NET trains classic models, and ONNX Runtime runs deep learning models fast on CPU or GPU.
The essential libraries
Gradient descent from scratch
Learn y = 3x + 0.5 with plain loops.
var rng = new Random(0);
int n = 100;
var xs = Enumerable.Range(0, n).Select(i => -1 + 2.0 * i / (n - 1)).ToArray();
var ys = xs.Select(x => 3 * x + 0.5 + 0.1 * (rng.NextDouble() - 0.5)).ToArray();
double w = 0, b = 0, lr = 0.1;
for (int step = 0; step < 500; step++) {
double gw = 0, gb = 0;
for (int i = 0; i < n; i++) {
double err = w * xs[i] + b - ys[i];
gw += 2 * err * xs[i] / n; gb += 2 * err / n;
}
w -= lr * gw; b -= lr * gb;
}
Console.WriteLine($"w={w:F2} b={b:F2}");Build an AI agent in C#
With System.Text.Json.Nodes you can run the agent loop directly against any OpenAI-compatible endpoint, here a local model in Ollama.
using System.Net.Http.Json;
using System.Text.Json.Nodes;
var http = new HttpClient();
var tools = JsonNode.Parse("""
[{"type":"function","function":{"name":"get_weather","description":"Weather for a city",
"parameters":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}}]
""");
var messages = new JsonArray(new JsonObject { ["role"] = "user", ["content"] = "Should I take an umbrella in Lahore today?" });
for (int round = 0; round < 5; round++) {
var body = new JsonObject { ["model"] = "llama3.1", ["messages"] = messages.DeepClone(), ["tools"] = tools!.DeepClone() };
var res = await http.PostAsJsonAsync("http://localhost:11434/v1/chat/completions", body);
var msg = (await res.Content.ReadFromJsonAsync<JsonNode>())!["choices"]![0]!["message"]!;
messages.Add(msg.DeepClone());
if (msg["tool_calls"] is not JsonArray calls || calls.Count == 0) { Console.WriteLine(msg["content"]); break; }
foreach (var call in calls) {
var city = JsonNode.Parse(call!["function"]!["arguments"]!.GetValue<string>())!["city"]!.GetValue<string>();
messages.Add(new JsonObject { ["role"] = "tool", ["tool_call_id"] = call["id"]!.GetValue<string>(), ["content"] = $"It is 24°C and sunny in {city}." });
}
}Semantic Kernel can do the same with C# methods marked as kernel functions, handling the loop for you.
ollama pull llama3.1, and keep it running. The code talks to its OpenAI-compatible API at http://localhost:11434/v1, so the same program also works with vLLM, llama.cpp server or a cloud API by changing the URL, model name and adding an API key.C# learning roadmap
Tick items off as you go. Your progress is saved in this browser.
Beginner
Intermediate
Advanced
Projects to build
C# cheat sheet
| Task | Syntax |
|---|---|
Console.WriteLine(x); | |
| Interpolate | $"{name} has {n}" |
| List | var l = new List<int>(); |
| LINQ | l.Where(x => x > 0) |
| Record | record P(int X, int Y); |
| Async | await http.GetStringAsync(url) |
Common mistakes
- Creating a new
HttpClientper request exhausts sockets; reuse one or useIHttpClientFactory. async voidswallows exceptions; returnTaskinstead.- Ignoring nullable warnings leads to NullReferenceException.
Where to go next
- Learn C# — official docs
- Semantic Kernel — agents in .NET
- ML.NET — ML for .NET
On TensorCore.si: Java volume, How AI works.
Keyboard: [ previous language · ] next language · / search the library