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.
📖 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
- Install
winget install Microsoft.DotNet.SDK.8
brew install --cask dotnet-sdk
see learn.microsoft.com/dotnet/core/install/linux for your distribution
- Editor: Visual Studio Code with C# Dev Kit (or Visual Studio).
- Create
Program.csConsole.WriteLine("Hello, GayaGnan!"); - Run it and check the version
dotnet new console -o hello && cd hello && dotnet run dotnet --version
- 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
- types
- control flow
- methods
- classes and interfaces
- collections
- LINQ
- exceptions
- async/await
- files
- xUnit testing
- ASP.NET Core minimal API
- dependency injection
- configuration and safe secrets
🏗️ Mini-projects
- Console quiz
- LINQ analytics
- REST service
- Mock ticketing system
Projects use synthetic data only.