iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Syntax

C# syntax tour: types, var, control flow, classes, records, generics, async/await, pattern matching.

C# — syntax tour

EXAMPLE
// ===== Primitives =====
int    age = 30;
long   id = 4_000_000_000L;
double pi = 3.14159;
decimal money = 49.95m;    // use for money
bool   ok = true;
char   ch = 'A';

// Reference / nullable:
string  name = "Alex";
string? maybe = null;       // requires <Nullable>enable</Nullable>

// var inference:
var users = new List<string>();
var pairs = new Dictionary<string, int>();

// ===== Control flow =====
if (age >= 18) { /* ... */ } else { /* ... */ }

for (int i = 0; i < 5; i++) { /* ... */ }
foreach (var x in users) { /* ... */ }

while (cond) { /* ... */ }
do { /* ... */ } while (cond);

// Switch expression (modern):
string size = age switch {
    0 or 1 => "baby",
    < 10 => "small",
    < 100 => "medium",
    _ => "large",
};

// Pattern matching with property patterns:
string describe(object o) => o switch {
    null => "nothing",
    int n when n < 0 => "negative int",
    int n => "int " + n,
    string s => "string " + s,
    { } x => x.ToString() ?? "obj",
};

// ===== Classes + records =====
public class User
{
    public int Id { get; }
    public string Name { get; set; }
    public User(int id, string name) { Id = id; Name = name; }
}

public record Order(int Id, string Customer, long TotalCents);
public record class OrderEntity(int Id) { public string? Note { get; init; } }
public record struct Point(int X, int Y);

// 'with' expressions (non-destructive update):
var p1 = new Point(1, 2);
var p2 = p1 with { X = 99 };

// ===== Generics =====
List<int> nums = new() { 1, 2, 3 };
Dictionary<string, int> ages = new() { ["Alex"] = 30 };

public static T First<T>(IReadOnlyList<T> xs) => xs[0];

// ===== async / await =====
public async Task<string> FetchAsync(string url)
{
    using var http = new HttpClient();
    return await http.GetStringAsync(url);
}

// ===== using + IDisposable =====
using var stream = File.OpenRead("a.txt");
// Disposed at end of scope.

// Long form:
using (var stream2 = File.OpenRead("b.txt")) { /* ... */ }

// ===== LINQ =====
using System.Linq;
var evens = new[] { 1, 2, 3, 4, 5 }.Where(n => n % 2 == 0).Select(n => n * n).ToList();

// ===== Tuples =====
(string Name, int Age) person = ("Alex", 30);
var (n, a) = person;

// ===== Patterns to internalise =====
// - Nullable reference types enabled in every project
// - record for value-shape DTOs
// - var for local readability
// - async / await at I/O boundaries
// - Pattern matching > nested ifs

// ===== Pitfalls =====
// - decimal vs double for money
// - .Result on Tasks -> deadlocks
// - Catching Exception broadly
// - Disabling nullable warnings -> hides real bugs

Why it matters

Modern C# is concise: var, record, pattern matching, switch expressions, nullable refs, async/await. Master those and the language stops being a wall of ceremony. Records + pattern matching alone reduce a startling amount of boilerplate.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
string name = "Ada";
Console.WriteLine(\$"Hello, {name}!");
Try it Yourself »

Discussion

Loading…