Feeling like you understand C# syntax but still struggle to build real applications on your own? That gap between watching and writing can be discouraging—but it disappears with consistent, hands-on practice. This post gives you 100 C# practice problems with clear, step-by-step solutions to help you write code with genuine confidence.
You’ll start with core basics like variables, loops, and arrays, then progress to object-oriented programming, LINQ, collections, exception handling, and working with files. Each problem is written in plain language—try it yourself first, then check the solution and truly understand the why behind the logic.
Why is practice so important? Because coding is a practical skill. Every problem you solve builds muscle memory, sharpens your debugging instincts, and turns abstract concepts into automatic habits. Whether you’re just getting started with C# or preparing for a technical interview, these exercises will make your learning stick and leave you feeling truly ready. Pick a problem, start coding, and experience that amazing “I’m really getting this!” moment.
Also try it: 100 .NET practice problems with solutions
1. Hello World
Write a program that prints “Hello, World!” to the console.
csharp
using System;
class Program {
static void Main() {
Console.WriteLine("Hello, World!");
}
}
2. Sum of Two Numbers
Write a method Sum that takes two integers and returns their sum.
csharp
int Sum(int a, int b) => a + b;
3. Check Even or Odd
Write a method that returns true if a number is even.
csharp
bool IsEven(int n) => n % 2 == 0;
4. Maximum of Three Numbers
csharp
int MaxOfThree(int a, int b, int c) => Math.Max(a, Math.Max(b, c));
5. Reverse a String
csharp
string ReverseString(string input) {
char[] chars = input.ToCharArray();
Array.Reverse(chars);
return new string(chars);
}
6. Palindrome Checker
Check if a string is a palindrome (ignore case and non‑alphanumeric).
csharp
bool IsPalindrome(string s) {
var clean = new string(s.Where(char.IsLetterOrDigit).ToArray()).ToLower();
return clean.SequenceEqual(clean.Reverse());
}
7. Count Vowels
Count the number of vowels in a string.
csharp
int CountVowels(string s) => s.Count(c => "aeiouAEIOU".Contains(c));
8. Find the Longest Word
Return the longest word in a sentence.
csharp
string LongestWord(string sentence) =>
sentence.Split(' ').OrderByDescending(w => w.Length).First();
9. Capitalize First Letter of Each Word
csharp
string CapitalizeWords(string s) =>
string.Join(" ", s.Split(' ').Select(w => char.ToUpper(w[0]) + w.Substring(1).ToLower()));
10. Truncate String with Ellipsis
csharp
string Truncate(string s, int maxLength) =>
s.Length > maxLength ? s.Substring(0, maxLength) + "..." : s;
11. Check Anagram
Two strings are anagrams if they contain the same characters with same frequency (case‑insensitive, ignore spaces).
csharp
bool AreAnagrams(string a, string b) {
var normalize = (string s) => new string(s.ToLower().Where(char.IsLetterOrDigit).OrderBy(c => c).ToArray());
return normalize(a) == normalize(b);
}
12. String Compression
Compress “aaabbc” to “a3b2c1”.
csharp
string Compress(string s) {
if (string.IsNullOrEmpty(s)) return "";
var result = new StringBuilder();
int count = 1;
for (int i = 1; i < s.Length; i++) {
if (s[i] == s[i - 1]) count++;
else { result.Append($"{s[i-1]}{count}"); count = 1; }
}
result.Append($"{s[^1]}{count}");
return result.ToString();
}
13. Find All Substrings
Print all substrings of a given string.
csharp
void PrintSubstrings(string s) {
for (int i = 0; i < s.Length; i++)
for (int j = i; j < s.Length; j++)
Console.WriteLine(s.Substring(i, j - i + 1));
}
14. Remove Duplicate Characters
csharp
string RemoveDuplicates(string s) => new string(s.Distinct().ToArray());
15. Convert String to Title Case
csharp
string ToTitleCase(string s) => System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());
16. Sum of Array Elements
csharp
int SumArray(int[] arr) => arr.Sum();
17. Find Min and Max
Return a tuple with the minimum and maximum.
csharp
(int min, int max) FindMinMax(int[] arr) => (arr.Min(), arr.Max());
18. Remove Negatives from an Array
csharp
int[] RemoveNegatives(int[] arr) => arr.Where(x => x >= 0).ToArray();
19. Reverse Array In-Place
csharp
void ReverseInPlace(int[] arr) {
for (int i = 0; i < arr.Length / 2; i++)
(arr[i], arr[arr.Length - 1 - i]) = (arr[arr.Length - 1 - i], arr[i]);
}
20. Merge Two Sorted Arrays
csharp
int[] MergeSorted(int[] a, int[] b) {
int[] res = new int[a.Length + b.Length];
int i = 0, j = 0, k = 0;
while (i < a.Length && j < b.Length)
res[k++] = a[i] < b[j] ? a[i++] : b[j++];
while (i < a.Length) res[k++] = a[i++];
while (j < b.Length) res[k++] = b[j++];
return res;
}
21. Remove Duplicates from Array
csharp
int[] RemoveDuplicates(int[] arr) => arr.Distinct().ToArray();
22. Rotate Array Right by K
csharp
int[] RotateRight(int[] arr, int k) {
k %= arr.Length;
return arr[^k..].Concat(arr[..^k]).ToArray();
}
23. Find Missing Number 1..N
Given array of size N‑1 with distinct numbers from 1 to N.
csharp
int FindMissing(int[] arr, int n) => n * (n + 1) / 2 - arr.Sum();
24. Find Intersection of Two Arrays
csharp
int[] Intersection(int[] a, int[] b) => a.Intersect(b).ToArray();
25. Find Union
csharp
int[] Union(int[] a, int[] b) => a.Union(b).ToArray();
26. Factorial (Recursive)
csharp
long Factorial(int n) => n == 0 ? 1 : n * Factorial(n - 1);
27. Fibonacci Sequence up to N
csharp
int[] Fibonacci(int n) {
int[] fib = new int[n];
if (n > 0) fib[0] = 0;
if (n > 1) fib[1] = 1;
for (int i = 2; i < n; i++) fib[i] = fib[i - 1] + fib[i - 2];
return fib;
}
28. Check Prime Number
csharp
bool IsPrime(int n) {
if (n < 2) return false;
for (int i = 2; i * i <= n; i++)
if (n % i == 0) return false;
return true;
}
29. FizzBuzz
Print numbers 1–100; multiples of 3 “Fizz”, of 5 “Buzz”, of both “FizzBuzz”.
csharp
void FizzBuzz() {
for (int i = 1; i <= 100; i++) {
if (i % 15 == 0) Console.WriteLine("FizzBuzz");
else if (i % 3 == 0) Console.WriteLine("Fizz");
else if (i % 5 == 0) Console.WriteLine("Buzz");
else Console.WriteLine(i);
}
}
30. Binary Search (Sorted Array)
csharp
int BinarySearch(int[] arr, int target) {
int left = 0, right = arr.Length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) return mid;
if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}
31. Bubble Sort
csharp
void BubbleSort(int[] arr) {
for (int i = 0; i < arr.Length - 1; i++)
for (int j = 0; j < arr.Length - i - 1; j++)
if (arr[j] > arr[j + 1])
(arr[j], arr[j + 1]) = (arr[j + 1], arr[j]);
}
32. QuickSort (Lomuto)
csharp
void QuickSort(int[] arr, int low, int high) {
if (low < high) {
int p = Partition(arr, low, high);
QuickSort(arr, low, p - 1);
QuickSort(arr, p + 1, high);
}
}
int Partition(int[] arr, int low, int high) {
int pivot = arr[high], i = low - 1;
for (int j = low; j < high; j++)
if (arr[j] < pivot) { i++; (arr[i], arr[j]) = (arr[j], arr[i]); }
(arr[i + 1], arr[high]) = (arr[high], arr[i + 1]);
return i + 1;
}
33. Linear Search
csharp
int LinearSearch(int[] arr, int target) => Array.IndexOf(arr, target);
34. Count Occurrences of an Element
csharp
int CountOccurrences(int[] arr, int val) => arr.Count(x => x == val);
35. Find Largest Element in 2D Array
csharp
int Max2D(int[,] matrix) {
int max = matrix[0, 0];
foreach (int item in matrix) if (item > max) max = item;
return max;
}
36. Create a Class Person
With properties Name and Age. Add a constructor and a method Introduce.
csharp
public class Person {
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age) { Name = name; Age = age; }
public string Introduce() => $"Hi, I'm {Name}, {Age} years old.";
}
37. Static Utility Class
csharp
public static class MathUtils {
public static double PI = 3.14159;
public static double Square(double x) => x * x;
}
38. Inheritance – Employee : Person
Add Salary property and override Introduce.
csharp
public class Employee : Person {
public decimal Salary { get; set; }
public Employee(string name, int age, decimal salary) : base(name, age) => Salary = salary;
public override string Introduce() => base.Introduce() + $" I earn {Salary:C}.";
}
39. Polymorphism – Shape Hierarchy
Abstract class Shape with abstract method GetArea(). Derived Circle and Rectangle.
csharp
public abstract class Shape { public abstract double GetArea(); }
public class Circle : Shape {
public double Radius { get; set; }
public override double GetArea() => Math.PI * Radius * Radius;
}
public class Rectangle : Shape {
public double Width { get; set; }
public double Height { get; set; }
public override double GetArea() => Width * Height;
}
40. Interface IDriveable with methods Start, Stop, Move.
csharp
public interface IDriveable {
void Start();
void Stop();
void Move();
}
public class Car : IDriveable {
public void Start() => Console.WriteLine("Car started.");
public void Stop() => Console.WriteLine("Car stopped.");
public void Move() => Console.WriteLine("Car moving.");
}
41. Multiple Interface Implementation
csharp
public interface IWalkable { void Walk(); }
public interface ISwimmable { void Swim(); }
public class Duck : IWalkable, ISwimmable {
public void Walk() => Console.WriteLine("Duck walks.");
public void Swim() => Console.WriteLine("Duck swims.");
}
42. Abstract Base Class with Virtual Method
csharp
public abstract class Animal {
public virtual void Speak() => Console.WriteLine("Animal sound");
}
public class Dog : Animal {
public override void Speak() => Console.WriteLine("Woof");
}
43. Sealed Class
csharp
public sealed class FinalClass { /* cannot be inherited */ }
44. Properties with Backing Fields
csharp
public class Product {
private decimal price;
public decimal Price {
get => price;
set { if (value >= 0) price = value; }
}
}
45. Indexer in Class
csharp
public class StringCollection {
private List<string> items = new();
public string this[int index] {
get => items[index];
set => items[index] = value;
}
public void Add(string item) => items.Add(item);
}
46. Constructor Overloading
csharp
public class Point {
public int X, Y;
public Point() : this(0, 0) { }
public Point(int x, int y) { X = x; Y = y; }
}
47. Destructor / Finalizer
csharp
public class ResourceHolder {
~ResourceHolder() => Console.WriteLine("Finalizer called.");
}
48. Method Overloading
csharp
public class MathOps {
public int Add(int a, int b) => a + b;
public double Add(double a, double b) => a + b;
public string Add(string a, string b) => a + b;
}
49. Operator Overloading (+)
csharp
public class Vector {
public int X, Y;
public Vector(int x, int y) { X = x; Y = y; }
public static Vector operator +(Vector a, Vector b) => new(a.X + b.X, a.Y + b.Y);
}
50. Record Type (C# 9+)
csharp
public record Customer(string Name, int Age);
51. LINQ – Filter Even Numbers
csharp
var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();
52. LINQ – Select Projection
csharp
var names = people.Select(p => p.Name);
53. LINQ – OrderBy
csharp
var sorted = products.OrderBy(p => p.Price).ToList();
54. LINQ – Group By
csharp
var groups = students.GroupBy(s => s.FieldOfStudy);
foreach (var g in groups)
Console.WriteLine($"{g.Key}: {g.Count()}");
55. LINQ – Join (Inner)
csharp
var joined = from p in people
join a in addresses on p.Id equals a.PersonId
select new { p.Name, a.City };
56. LINQ – FirstOrDefault
csharp
var firstAdult = people.FirstOrDefault(p => p.Age >= 18);
57. LINQ – Any & All
csharp
bool hasMinors = people.Any(p => p.Age < 18); bool allAdults = people.All(p => p.Age >= 18);
58. LINQ – Distinct and Count
csharp
int uniqueCities = addresses.Select(a => a.City).Distinct().Count();
59. LINQ – Take/Skip (Pagination)
csharp
var page = items.Skip((pageNo - 1) * pageSize).Take(pageSize);
60. LINQ – Aggregate (Sum, Average, Max)
csharp
double avg = salaries.Average(); decimal total = prices.Sum();
61. Simple Delegate
csharp
delegate int Operation(int a, int b); // Usage: Operation add = (x, y) => x + y; Console.WriteLine(add(2,3));
62. Func and Action
csharp
Func<int, int, int> multiply = (x, y) => x * y; Action<string> print = msg => Console.WriteLine(msg);
63. Predicate Delegate
csharp
Predicate<int> isPositive = n => n > 0;
64. Anonymous Method
csharp
Func<int, int> square = delegate(int x) { return x * x; };
65. Lambda Expressions
csharp
List<int> list = new() { 1,2,3,4,5 };
var squares = list.Select(x => x * x);
66. Event and EventHandler
csharp
public class Button {
public event EventHandler Clicked;
public void Press() => Clicked?.Invoke(this, EventArgs.Empty);
}
// subscriber
button.Clicked += (sender, e) => Console.WriteLine("Button clicked!");
67. Multicast Delegate
csharp
Action greet = () => Console.WriteLine("Hello");
greet += () => Console.WriteLine("World");
greet(); // prints Hello and World
68. Closure in Lambdas
csharp
int factor = 2; Func<int, int> multiplier = x => x * factor; Console.WriteLine(multiplier(5)); // 10
69. Delegate with Callback
csharp
void Process(int num, Action<int> callback) => callback(num); Process(5, res => Console.WriteLine(res));
70. Custom EventArgs and Event
csharp
public class CustomEventArgs : EventArgs { public string Message { get; set; } }
public delegate void CustomEventHandler(object sender, CustomEventArgs e);
public class Publisher {
public event CustomEventHandler OnCustomEvent;
public void Trigger() => OnCustomEvent?.Invoke(this, new CustomEventArgs { Message = "Event fired" });
}
71. Try-Catch Basic
csharp
try { int x = int.Parse("abc"); }
catch (FormatException ex) { Console.WriteLine(ex.Message); }
72. Multiple Catch Blocks
csharp
try { /* ... */ }
catch (DivideByZeroException) { /* ... */ }
catch (Exception ex) { Console.WriteLine(ex.Message); }
73. Finally Block
csharp
StreamReader reader = null;
try { reader = File.OpenText("file.txt"); string content = reader.ReadToEnd(); }
finally { reader?.Close(); }
Also try it: 100 C++ practice problems with solutions
74. Using Statement (IDisposable)
csharp
using (var reader = File.OpenText("file.txt")) { Console.WriteLine(reader.ReadToEnd()); }
75. Custom Exception
csharp
public class InvalidAgeException : Exception {
public InvalidAgeException(string msg) : base(msg) { }
}
throw new InvalidAgeException("Age must be positive.");
76. Read All Lines from a File
csharp
string[] lines = File.ReadAllLines("data.txt");
77. Write Text to File
csharp
File.WriteAllText("output.txt", "Hello, C#");
78. Append to File
csharp
File.AppendAllText("log.txt", DateTime.Now + ": Log entry\n");
79. File Exists Check
csharp
if (File.Exists("input.txt")) Console.WriteLine("File exists.");
80. Read File Line by Line (Stream)
csharp
using var reader = new StreamReader("data.txt");
while (!reader.EndOfStream) Console.WriteLine(reader.ReadLine());
81. Async Method and Await
csharp
async Task<string> DownloadDataAsync(string url) {
using var http = new HttpClient();
return await http.GetStringAsync(url);
}
82. Task.WhenAll
csharp
async Task<string[]> FetchMultipleAsync(IEnumerable<string> urls) {
var tasks = urls.Select(u => new HttpClient().GetStringAsync(u));
return await Task.WhenAll(tasks);
}
83. Task.Run for CPU-Bound Work
csharp
Task<int> compute = Task.Run(() => {
int sum = 0;
for (int i = 0; i < 1000; i++) sum += i;
return sum;
});
int result = await compute;
84. CancellationToken
csharp
async Task LongRunningAsync(CancellationToken ct) {
while (!ct.IsCancellationRequested) {
await Task.Delay(100, ct);
}
}
85. Async with Timeout
csharp
async Task<string> FetchWithTimeout(string url, int timeoutMs) {
using var cts = new CancellationTokenSource(timeoutMs);
return await new HttpClient().GetStringAsync(url, cts.Token);
}
86. Recursive Factorial with Memoization
csharp
Dictionary<int, long> memo = new();
long MemoFactorial(int n) {
if (n <= 1) return 1;
if (memo.ContainsKey(n)) return memo[n];
memo[n] = n * MemoFactorial(n - 1);
return memo[n];
}
87. Stack Implementation
csharp
public class Stack<T> {
private List<T> list = new();
public void Push(T item) => list.Add(item);
public T Pop() { T item = Peek(); list.RemoveAt(list.Count - 1); return item; }
public T Peek() => list[^1];
public int Count => list.Count;
}
88. Queue Implementation
csharp
public class Queue<T> {
private LinkedList<T> list = new();
public void Enqueue(T item) => list.AddLast(item);
public T Dequeue() { T item = Peek(); list.RemoveFirst(); return item; }
public T Peek() => list.First.Value;
public int Count => list.Count;
}
89. Singly Linked List Node
csharp
public class Node<T> {
public T Data { get; set; }
public Node<T> Next { get; set; }
public Node(T data) => Data = data;
}
90. Reverse a Singly Linked List
csharp
Node<T> ReverseList<T>(Node<T> head) {
Node<T> prev = null, current = head;
while (current != null) {
Node<T> next = current.Next;
current.Next = prev;
prev = current;
current = next;
}
return prev;
}
Also try it: 100 Azure practice problems with solutions
91. Find Length of Linked List
csharp
int Length<T>(Node<T> head) {
int count = 0;
while (head != null) { count++; head = head.Next; }
return count;
}
92. Palindrome Linked List
csharp
bool IsPalindrome(Node<char> head) {
var stack = new Stack<char>();
var slow = head; var fast = head;
while (fast != null && fast.Next != null) {
stack.Push(slow.Data);
slow = slow.Next;
fast = fast.Next.Next;
}
if (fast != null) slow = slow.Next; // odd length
while (slow != null) {
if (stack.Pop() != slow.Data) return false;
slow = slow.Next;
}
return true;
}
93. Binary Tree Node and In-Order Traversal
csharp
public class TreeNode {
public int Val;
public TreeNode Left, Right;
public TreeNode(int val) => Val = val;
}
void InOrder(TreeNode root) {
if (root == null) return;
InOrder(root.Left);
Console.Write(root.Val + " ");
InOrder(root.Right);
}
94. Find Height of Binary Tree
csharp
int Height(TreeNode root) {
if (root == null) return 0;
return 1 + Math.Max(Height(root.Left), Height(root.Right));
}
95. Check if Binary Tree is Mirror (Symmetric)
csharp
bool IsSymmetric(TreeNode root) => IsMirror(root, root);
bool IsMirror(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) return true;
if (t1 == null || t2 == null) return false;
return (t1.Val == t2.Val) && IsMirror(t1.Left, t2.Right) && IsMirror(t1.Right, t2.Left);
}
96. Generate Permutations of a String
csharp
void Permute(string s, int l, int r) {
if (l == r) Console.WriteLine(s);
else {
char[] arr = s.ToCharArray();
for (int i = l; i <= r; i++) {
(arr[l], arr[i]) = (arr[i], arr[l]);
Permute(new string(arr), l + 1, r);
(arr[l], arr[i]) = (arr[i], arr[l]); // backtrack
}
}
}
97. Binary Search Tree Insertion
csharp
TreeNode InsertBST(TreeNode root, int val) {
if (root == null) return new TreeNode(val);
if (val < root.Val) root.Left = InsertBST(root.Left, val);
else root.Right = InsertBST(root.Right, val);
return root;
}
98. Check if Two Strings are One Edit Away
csharp
bool OneEditAway(string a, string b) {
int m = a.Length, n = b.Length;
if (Math.Abs(m - n) > 1) return false;
int i = 0, j = 0, edits = 0;
while (i < m && j < n) {
if (a[i] != b[j]) {
if (++edits > 1) return false;
if (m > n) i++;
else if (m < n) j++;
else { i++; j++; }
} else { i++; j++; }
}
if (i < m || j < n) edits++;
return edits <= 1;
}
99. LRU Cache (Simplified using LinkedList and Dictionary)
csharp
public class LRUCache {
private record CacheItem(int Key, int Value);
private LinkedList<CacheItem> list = new();
private Dictionary<int, LinkedListNode<CacheItem>> map = new();
private int capacity;
public LRUCache(int capacity) => this.capacity = capacity;
public int Get(int key) {
if (!map.ContainsKey(key)) return -1;
var node = map[key];
list.Remove(node); list.AddFirst(node);
return node.Value.Value;
}
public void Put(int key, int value) {
if (map.ContainsKey(key)) {
var node = map[key];
list.Remove(node);
list.AddFirst(new LinkedListNode<CacheItem>(new CacheItem(key, value)));
map[key] = list.First;
return;
}
if (map.Count >= capacity) {
var last = list.Last; map.Remove(last.Value.Key); list.RemoveLast();
}
var newNode = new LinkedListNode<CacheItem>(new CacheItem(key, value));
list.AddFirst(newNode);
map[key] = newNode;
}
}
100. Simple Dependency Injection Container
csharp
public class DIContainer {
private Dictionary<Type, Type> registrations = new();
public void Register<TInterface, TImplementation>() where TImplementation : TInterface =>
registrations[typeof(TInterface)] = typeof(TImplementation);
public TInterface Resolve<TInterface>() {
var type = registrations[typeof(TInterface)];
return (TInterface)Activator.CreateInstance(type);
}
}
Conclusion: Turning Effort into C# Confidence
Working through these 100 C# practice problems with solutions is a powerful achievement. Each problem you completed added a new layer to your understanding of programming logic, object-oriented concepts, and problem-solving skills.
There may have been moments of confusion or frustration, but those moments are what shape real developers. Every error fixed and every solution understood is proof that your skills are growing stronger with time.
C# is a language built for creating strong and reliable applications, and with consistent practice like this, you are building the foundation to create something meaningful in the future. Keep challenging yourself, keep writing code, and remember—progress comes from persistence, not perfection.