👑 Premium Sign in Sign up

Language lab · Beginner → Cloud

🟪 C#

Concept → trace → write code → run tests → explain why → improve → mini-project. Start in the browser if you like; set up your own computer when you are ready.

💻 Runs on your computerOfficial download & docs ↗

📖 Topics with real code (16)

Every verified output below was produced by running the code with 8.0.427 on 5 Nov 2026. Open a topic to edit the code and run it on your own computer with the real compiler, through the free GayaGnan agent.

🌱 Beginner (5)

Variables and data types

C# types: int, long, double, decimal (exact money), bool, char, string. var infers the type. int.Parse and Convert change text to numbers; casts change numeric types.

int age = 15;
long population = 1_428_000_000L;
double height = 1.62;
decimal price = 49.99m;
bool isStudent = true;
char grade = 'A';
string name = "Asha";
var city = "Hyderabad";
Console.WriteLine($"{name} {age} {height} {isStudent} {grade} {city}");
Console.WriteLine($"population {population}, price {price}, int max {int.MaxValue}");
int marks = int.Parse("88") + 2;
double avg = (double)7 / 2;
Console.WriteLine($"{marks} {avg} {7 / 2} {(int)9.99} {0.1 + 0.2 == 0.3} {0.1m + 0.2m == 0.3m}");

✅ Verified output

Asha 15 1.62 True A Hyderabad
population 1428000000, price 49.99, int max 2147483647
90 3.5 3 9 False True
Operators and boolean logic

&& and || short-circuit; == compares values (for strings too). ?? supplies a default for null, and ?. skips a call on null.

int a = 17, b = 5;
Console.WriteLine($"{a + b} {a - b} {a * b} {a / b} {a % b} {Math.Pow(a, 2)}");
bool hasTicket = true, isVip = false;
Console.WriteLine($"enter: {hasTicket && !isVip} either: {hasTicket || isVip}");
string? nickname = null;
Console.WriteLine($"{nickname ?? "no nickname"} length: {nickname?.Length ?? 0}");
Console.WriteLine($"{"hello" == "hel" + "lo"} 6&3={6 & 3} 1<<4={1 << 4}");
int x = 5;
x += 3; x *= 2; x++;
Console.WriteLine($"x={x}");

✅ Verified output

22 12 85 3 2 289
enter: True either: True
no nickname length: 0
True 6&3=2 1<<4=16
x=17
Conditionals: if, switch expressions and patterns

if/else picks a branch. A switch expression returns a value and can match ranges with relational patterns.

int marks = 78;
string grade = marks switch
{
    >= 90 => "A+",
    >= 75 => "A",
    >= 35 => "Pass",
    _ => "Fail",
};
Console.WriteLine($"Grade: {grade}");
var day = DayOfWeek.Saturday;
if (day is DayOfWeek.Saturday or DayOfWeek.Sunday) Console.WriteLine("Weekend");
else Console.WriteLine("School day");
Console.WriteLine(marks >= 35 ? "passed" : "try again");

✅ Verified output

Grade: A
Weekend
passed
Loops: for, while, foreach

for counts, while repeats, foreach walks collections. break and continue control the loop.

for (int i = 1; i <= 5; i++)
{
    if (i == 3) continue;
    Console.WriteLine($"for {i}");
}
int n = 10;
while (n > 0)
{
    if (n < 4) break;
    Console.WriteLine($"while {n}");
    n -= 3;
}
foreach (var c in new[] { "red", "green" }) Console.WriteLine($"each {c}");
for (int r = 1; r <= 3; r++)
{
    var row = "";
    for (int c = 1; c <= 3; c++) row += (r * c).ToString().PadLeft(3);
    Console.WriteLine(row);
}

✅ Verified output

for 1
for 2
for 4
for 5
while 10
while 7
while 4
each red
each green
  1  2  3
  2  4  6
  3  6  9
Methods: optional, named, out and ref parameters

Local functions with optional and named arguments. ref lets a method change the caller's variable; out returns an extra value.

static int Area(int length, int width = 1) => length * width;
static void AddBonus(ref int marks, int bonus = 5) => marks += bonus;
static bool TryHalf(int n, out int half)
{
    half = n / 2;
    return n % 2 == 0;
}
static double Average(params int[] nums) => nums.Average();

Console.WriteLine($"{Area(5, 3)} {Area(7)} {Area(width: 2, length: 9)}");
int m = 80;
AddBonus(ref m);
Console.WriteLine($"marks {m}, average {Average(4, 9, 2, 7)}");
if (TryHalf(10, out int h)) Console.WriteLine($"half {h}");

✅ Verified output

15 7 18
marks 85, average 5.5
half 5

🌿 Intermediate (7)

Arrays and List<T>

Arrays are fixed size; List<T> grows. LINQ methods (Where, Select, OrderBy, Sum) query them.

int[] fixedMarks = { 72, 95, 64, 88 };
Array.Sort(fixedMarks);
Console.WriteLine(string.Join(", ", fixedMarks));
var marks = new List<int> { 72, 95, 64, 88 };
marks.Add(91);
marks.Sort();
Console.WriteLine($"first {marks[0]} last {marks[^1]} count {marks.Count} top2 {string.Join(",", marks[^2..])}");
var oddSquares = Enumerable.Range(1, 5).Where(x => x % 2 == 1).Select(x => x * x).ToList();
Console.WriteLine($"odd squares {string.Join(" ", oddSquares)} sum {oddSquares.Sum()}");
int[,] grid = { { 1, 2 }, { 3, 4 } };
Console.WriteLine($"grid[1,0] = {grid[1, 0]}");

✅ Verified output

64, 72, 88, 95
first 64 last 95 count 5 top2 91,95
odd squares 1 9 25 sum 35
grid[1,0] = 3
Strings and StringBuilder

Strings are immutable; $"..." interpolates values with formats. StringBuilder is efficient in loops.

using System.Text;

var t = "  GayaGnan learning  ".Trim();
Console.WriteLine($"{t.ToUpper()} | {t.Replace("learning", "labs")} | {t.Length}");
var words = t.Split(' ');
Console.WriteLine($"{string.Join("-", words)} contains Gnan: {t.Contains("Gnan")}");
Console.WriteLine($"Total: {49.5 * 3:F2} for {3} items, padded [{42,6}]");
var sb = new StringBuilder();
for (int i = 1; i <= 5; i++) sb.Append(i).Append(i < 5 ? "," : "");
Console.WriteLine(sb);
var p = "level";
Console.WriteLine($"palindrome: {p == new string(p.Reverse().ToArray())}");

✅ Verified output

GAYAGNAN LEARNING | GayaGnan labs | 17
GayaGnan-learning contains Gnan: True
Total: 148.50 for 3 items, padded [    42]
1,2,3,4,5
palindrome: True
Dictionary and HashSet

Dictionary<K,V> maps keys to values; TryGetValue avoids exceptions; HashSet<T> keeps unique items with set operations.

var stock = new SortedDictionary<string, int> { ["pen"] = 40, ["book"] = 12 };
stock["eraser"] = 25;
stock["pen"] -= 5;
foreach (var (item, count) in stock) Console.WriteLine($"{item} {count}");
Console.WriteLine($"has ruler? {stock.ContainsKey("ruler")}, {(stock.TryGetValue("book", out var b) ? b : 0)} books");
var a = new HashSet<string> { "maths", "science", "art" };
a.IntersectWith(new[] { "science", "music" });
Console.WriteLine($"both: {string.Join(",", a)}");
var freq = "the cat and the hat and the bat".Split(' ').GroupBy(w => w).OrderBy(g => g.Key).Select(g => $"{g.Key}={g.Count()}");
Console.WriteLine(string.Join(" ", freq));

✅ Verified output

book 12
eraser 25
pen 35
has ruler? False, 12 books
both: science
and=2 bat=1 cat=1 hat=1 the=3
Classes, properties and records

Properties wrap fields with get/set rules. A record is an immutable data type with value equality and a nice ToString.

var acc = new BankAccount("Asha", 500);
acc.Deposit(250);
Console.WriteLine($"{acc.Owner} {acc.Balance}");
var s = new Student("Ravi", 95);
Console.WriteLine($"{s} equal: {s == new Student("Ravi", 95)} with: {s with { Marks = 99 }}");

class BankAccount
{
    public string Owner { get; }
    public decimal Balance { get; private set; }
    public BankAccount(string owner, decimal balance) { Owner = owner; Balance = balance; }
    public void Deposit(decimal amount)
    {
        if (amount <= 0) throw new ArgumentException("amount must be positive");
        Balance += amount;
    }
}
record Student(string Name, int Marks);

✅ Verified output

Asha 750
Student { Name = Ravi, Marks = 95 } equal: True with: Student { Name = Ravi, Marks = 99 }
Interfaces, inheritance and polymorphism

An interface is a contract; abstract classes share code; virtual/override changes behaviour in subclasses.

var shapes = new IShape[] { new Circle(1), new Rect(3, 4) };
foreach (var s in shapes) Console.WriteLine($"{s.GetType().Name} {s.Area():F2}");
Animal a = new Dog();
Console.WriteLine($"Dog {a.Speak()}, is Animal: {a is Animal}");

interface IShape { double Area(); }
class Circle(double r) : IShape { public double Area() => Math.PI * r * r; }
class Rect(double w, double h) : IShape { public double Area() => w * h; }
abstract class Animal
{
    protected abstract string Sound();
    public virtual string Speak() => $"says {Sound()}";
}
class Dog : Animal { protected override string Sound() => "Woof"; }

✅ Verified output

Circle 3.14
Rect 12.00
Dog says Woof, is Animal: True
Exceptions

try/catch/finally with typed catches and exception filters (when). using disposes resources automatically.

try
{
    int zero = 0;
    Console.WriteLine(10 / zero);
}
catch (DivideByZeroException e)
{
    Console.WriteLine($"DivideByZeroException: {e.Message}");
}
finally
{
    Console.WriteLine("finally always runs");
}
try
{
    throw new InsufficientFundsException(50);
}
catch (InsufficientFundsException e) when (e.Shortfall > 10)
{
    Console.WriteLine($"Custom: need {e.Shortfall} more");
}
Console.WriteLine(int.TryParse("abc", out _) ? "number" : "not a number");

class InsufficientFundsException(decimal shortfall) : Exception($"short by {shortfall}")
{
    public decimal Shortfall { get; } = shortfall;
}

✅ Verified output

DivideByZeroException: Attempted to divide by zero.
finally always runs
Custom: need 50 more
not a number
Files with System.IO

File.WriteAllText and File.ReadAllLines handle simple text files; Path.GetTempFileName makes a safe temp file.

var path = Path.GetTempFileName();
File.WriteAllText(path, "name,marks\nAsha,88\nRavi,95\n");
var rows = File.ReadAllLines(path).Skip(1).Select(l => l.Split(',')).Select(p => (Name: p[0], Marks: int.Parse(p[1]))).ToList();
foreach (var r in rows) Console.WriteLine($"{r.Name} -> {r.Marks}");
Console.WriteLine($"average {rows.Average(r => r.Marks)}");
File.Delete(path);
Console.WriteLine($"deleted: {!File.Exists(path)}");

✅ Verified output

Asha -> 88
Ravi -> 95
average 91.5
deleted: True

🌳 Advanced (4)

Recursion and memoization

A Dictionary cache makes recursive Fibonacci fast. long holds fib(80).

var memo = new Dictionary<int, long>();
long Fib(int n)
{
    if (n < 2) return n;
    if (memo.TryGetValue(n, out var v)) return v;
    return memo[n] = Fib(n - 1) + Fib(n - 2);
}
int BinarySearch(int[] a, int t, int lo, int hi)
{
    if (lo > hi) return -1;
    int mid = lo + (hi - lo) / 2;
    if (a[mid] == t) return mid;
    return a[mid] < t ? BinarySearch(a, t, mid + 1, hi) : BinarySearch(a, t, lo, mid - 1);
}
Console.WriteLine(string.Join(" ", Enumerable.Range(0, 10).Select(Fib)) + $" | fib(80) = {Fib(80)}");
int[] sorted = { 2, 5, 8, 12, 16, 23, 38 };
Console.WriteLine($"index of 23: {BinarySearch(sorted, 23, 0, sorted.Length - 1)}");

✅ Verified output

0 1 1 2 3 5 8 13 21 34 | fib(80) = 23416728348467685
index of 23: 5
Generics, delegates and LINQ

Generic methods work for any type that meets a constraint. Func<T,T> is a delegate (a function value). LINQ groups and orders data.

static T MaxOf<T>(IEnumerable<T> items) where T : IComparable<T> => items.Aggregate((a, b) => a.CompareTo(b) >= 0 ? a : b);
static T ApplyTwice<T>(Func<T, T> f, T x) => f(f(x));

var students = new[] { new { Name = "Asha", Cls = "8A", Marks = 88 }, new { Name = "Ravi", Cls = "8B", Marks = 95 }, new { Name = "Meena", Cls = "8A", Marks = 72 } };
Console.WriteLine(string.Join(",", students.Where(s => s.Marks >= 80).Select(s => s.Name)));
foreach (var g in students.GroupBy(s => s.Cls).OrderBy(g => g.Key)) Console.WriteLine($"{g.Key}: avg {g.Average(s => s.Marks)}");
Console.WriteLine($"{MaxOf(new[] { 4, 9, 2 })} {MaxOf(new[] { "kiwi", "mango" })} {ApplyTwice(n => n * 3, 2)} {ApplyTwice(s => s + "!", "hi")}");

✅ Verified output

Asha,Ravi
8A: avg 80
8B: avg 95
9 mango 18 hi!!
async/await and parallel work

Task.WhenAll runs async waits together, so three 200 ms delays take about 200 ms. Interlocked makes a counter safe across Parallel.For threads.

using System.Diagnostics;

var sw = Stopwatch.StartNew();
async Task<int> SlowSquare(int n) { await Task.Delay(200); return n * n; }
var results = await Task.WhenAll(SlowSquare(1), SlowSquare(2), SlowSquare(3));
Console.WriteLine($"squares {string.Join(",", results)} fast: {sw.ElapsedMilliseconds < 550}");
int counter = 0;
Parallel.For(0, 4, _ => { for (int i = 0; i < 1000; i++) Interlocked.Increment(ref counter); });
Console.WriteLine($"counter {counter}");

✅ Verified output

squares 1,4,9 fast: True
counter 4000
Value types vs reference types

struct values are copied; class objects are shared by reference. Span<T> gives a fast view into an array without copying.

var p1 = new PointStruct { X = 1 };
var p2 = p1;          // copy
p2.X = 99;
var c1 = new PointClass { X = 1 };
var c2 = c1;          // same object
c2.X = 99;
Console.WriteLine($"struct: {p1.X} {p2.X} | class: {c1.X} {c2.X} same: {ReferenceEquals(c1, c2)}");
int[] data = { 10, 20, 30, 40, 50 };
Span<int> middle = data.AsSpan(1, 3);
middle[0] = 0;
Console.WriteLine($"span changed the array: {string.Join(",", data)}");

struct PointStruct { public int X; }
class PointClass { public int X; }

✅ Verified output

struct: 1 99 | class: 99 99 same: True
span changed the array: 10,0,30,40,50

💻 Terminal on my computer

Like a cloud shell, but on your own laptop: install compilers and run real commands from this page through the free GayaGnan agent. It asks you before connecting, installing or running anything.

🛠️ Set up and verify

  1. Install
    winget install Microsoft.DotNet.SDK.8
    brew install --cask dotnet-sdk
    see learn.microsoft.com/dotnet/core/install/linux for your distribution
  2. Editor: Visual Studio Code with C# Dev Kit (or Visual Studio).
  3. Create Program.cs
    Console.WriteLine("Hello, GayaGnan!");
  4. Run it and check the version
    dotnet new console -o hello && cd hello && dotnet run
    dotnet --version
  5. Health check: paste what your terminal printed.

Install one language at a time. These commands only install or print versions; nothing here deletes files. Versions change: check the official page and note the version you installed.

🧭 The 14-lab path

  • 00 · Setup and verify — install the runtime and editor, run hello world, print the version, fix PATH
  • 01 · Syntax and trace — follow each line and the value of every variable
  • 02 · Logic — conditionals and decision trees
  • 03 · Loops — trace tables and loop challenges
  • 04 · Functions — break problems down and test each piece
  • 05 · Data structures — lists, maps, stacks, queues and trees you can see
  • 06 · Debugging — bug cases with a hint ladder
  • 07 · Algorithms — search, sort and Big-O comparison
  • 08 · Files and data — read and write fixture files
  • 09 · API or database — talk to a mock API or a sandbox database
  • 10 · Testing — write tests and read failing assertions
  • 11 · Security — secure coding and dependency hygiene for this language
  • 12 · Project — one portfolio mini-project
  • 13 · Assessment — quiz, coding test, rubric and an explain-your-answer prompt

📚 Modules

  1. types
  2. control flow
  3. methods
  4. classes and interfaces
  5. collections
  6. LINQ
  7. exceptions
  8. async/await
  9. files
  10. xUnit testing
  11. ASP.NET Core minimal API
  12. dependency injection
  13. configuration and safe secrets

🏗️ Mini-projects

  • Console quiz
  • LINQ analytics
  • REST service
  • Mock ticketing system

Projects use synthetic data only.