Easy Learn C#

Welcome to Easy Learn C#

Your journey to mastering C# programming starts here! Whether you're a complete beginner or looking to enhance your skills, our platform provides clear, concise, and beginner-friendly tutorials.

Basic C#

Learn the fundamentals of C# programming including variables, data types, control structures, and more.

Start Beginner Course

Object-Oriented Programming

Master object-oriented programming principles with C# classes, inheritance, polymorphism, and more.

Learn OOP

Quick Start: Your First C# Program

Hello World Example:


using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");    
        }
    }
}
                            

This simple program displays "Hello World!" to the console when executed.

  • using System; - Imports the System namespace for basic functionality
  • namespace HelloWorld - Creates a container for your code
  • class Program - Defines a class to hold your methods
  • static void Main(string[] args) - The entry point of your program
  • Console.WriteLine("Hello World!"); - Outputs text to the console

Introduction to C#

What is C#?

C# (pronounced "C-sharp") is a modern, object-oriented programming language developed by Microsoft as part of its .NET initiative. It was designed by Anders Hejlsberg and his team and first released in 2000.

C# is designed to be:

  • Simple - C# removes complexities and provides a clean syntax
  • Modern - Includes features for contemporary software development
  • Object-Oriented - Based on the principles of encapsulation, inheritance, and polymorphism
  • Type-Safe - Helps you avoid errors by checking types at compile time
  • Versatile - Can be used for desktop applications, web services, mobile apps, games, and more

Why Learn C#?

C# offers numerous advantages for developers:

  • Industry Demand - C# developers are in high demand globally
  • Microsoft Support - Regularly updated with new features and improvements
  • Versatility - Used in web development (ASP.NET), desktop applications (WPF, WinForms), game development (Unity), mobile apps (Xamarin), and more
  • Rich Libraries - Access to the extensive .NET Framework and .NET Core libraries
  • Community - Large community with abundant learning resources and support

Setting Up C# Development Environment

Visual Studio

Visual Studio is Microsoft's primary IDE for C# development. It offers a complete development environment with advanced debugging, IntelliSense, and integrated tools.

Installation Steps:

  1. Visit Visual Studio website
  2. Download Visual Studio Community (free) or other editions
  3. Run the installer and select ".NET desktop development" workload
  4. Follow the installation wizard to complete setup

Visual Studio Code

Visual Studio Code is a lightweight, cross-platform code editor that can be configured for C# development.

Setup for C# Development:

  1. Download and install Visual Studio Code
  2. Install the C# extension from the marketplace
  3. Install the .NET SDK

Creating Your First Project

Once you have your development environment set up, you can create your first C# project:

Using Visual Studio:

  1. Open Visual Studio
  2. Click "Create a new project"
  3. Select "Console App (.NET Core)" or "Console App (.NET Framework)"
  4. Name your project and click "Create"

Using Command Line:


# Create a new console application
dotnet new console -n MyFirstApp

# Navigate to the project directory
cd MyFirstApp

# Run the application
dotnet run
                        

C# Syntax

Basic Syntax

C# syntax is similar to other C-style languages like C, C++, and Java. If you know any of these languages, C# syntax will look familiar.

Example:


using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}
                            

Let's break down this code:

  • using System; - This line imports the System namespace which contains the Console class
  • namespace HelloWorld { ... } - Groups your code into a namespace called "HelloWorld"
  • class Program { ... } - Defines a class called "Program"
  • static void Main(string[] args) { ... } - The Main method is the entry point of your program
  • Console.WriteLine("Hello World!"); - Prints text to the console

C# Statement Structure

In C#, statements end with a semicolon (;) and code blocks are enclosed in curly braces { }.


// Single statements end with semicolons
int x = 10;
Console.WriteLine(x);

// Code blocks use curly braces
if (x > 5) 
{
    Console.WriteLine("x is greater than 5");
    x = 5;  // This is also within the block
}

// Single statement blocks can omit braces (not recommended)
if (x == 5)
    Console.WriteLine("x equals 5");  // Only this line is in the if block
                            

Important notes:

  • Every statement must end with a semicolon
  • Code blocks define the scope of variables declared within them
  • While you can omit braces for single-statement blocks, it's generally not recommended for readability and to prevent bugs

C# Case Sensitivity

C# is a case-sensitive language. This means that myVariable and MyVariable are considered different identifiers.


// These are three different variables
int value = 10;
int Value = 20;
int VALUE = 30;

// This works
Console.WriteLine(value);  // Outputs: 10
Console.WriteLine(Value);  // Outputs: 20
Console.WriteLine(VALUE);  // Outputs: 30

// This would cause an error
// Console.WriteLine(vAlUe);  // Variable 'vAlUe' doesn't exist
                            

C# Comments

Comments are used to explain code and are ignored by the compiler.


// This is a single-line comment

/* This is a 
   multi-line comment */

/// <summary>
/// XML documentation comments are used to generate documentation
/// </summary>
public void DocumentedMethod()
{
    // Method implementation
}
                            

C# supports three types of comments:

  • // Single-line comments - Everything after // on that line is a comment
  • /* Multi-line comments */ - Everything between /* and */ is a comment, even across multiple lines
  • /// XML documentation comments - Special comments that can be used to generate documentation

C# Coding Conventions

Following are some common C# coding conventions:

  • PascalCase: Used for class names, method names, and public members (e.g., ClassName, MethodName)
  • camelCase: Used for local variables and parameters (e.g., localVariable, parameterName)
  • _camelCase: Often used for private fields (e.g., _privateField)
  • ALL_CAPS: Sometimes used for constants (e.g., MAX_SIZE)
  • Braces on their own line (typically) for methods and classes
  • Use four spaces for indentation (or a tab set to four spaces)

C# Output

Console Output

To output text to the console in C#, you use the Console.WriteLine() and Console.Write() methods.

Example:


// WriteLine adds a new line after the output
Console.WriteLine("Hello World!");
Console.WriteLine("I am learning C#");

// Write doesn't add a new line
Console.Write("Hello ");
Console.Write("World");  // Output: Hello World (on the same line)
                            
  • Console.WriteLine() prints the specified text followed by a new line
  • Console.Write() prints the specified text without a new line

Formatting Output

You can format your output in different ways:

String Concatenation:


string name = "John";
int age = 25;
Console.WriteLine("Name: " + name + ", Age: " + age);
                            

String Formatting (composite formatting):


string name = "John";
int age = 25;
Console.WriteLine("Name: {0}, Age: {1}", name, age);
                            

String Interpolation (recommended, C# 6.0 and later):


string name = "John";
int age = 25;
Console.WriteLine($"Name: {name}, Age: {age}");
                            

Formatting Numbers and Dates

You can format numbers and dates using format specifiers:

Currency Formatting:


double price = 123.45;
Console.WriteLine($"Price: {price:C}");  // Outputs: Price: $123.45 (in US culture)
                            

Number Formatting:


double number = 12345.6789;
Console.WriteLine($"Number: {number:N2}");  // Outputs: Number: 12,345.68 (formatted with commas and 2 decimal places)
Console.WriteLine($"Percentage: {0.75:P0}");  // Outputs: Percentage: 75%
                            

Date Formatting:


DateTime now = DateTime.Now;
Console.WriteLine($"Date: {now:d}");  // Outputs: Date: 5/10/2023 (short date format)
Console.WriteLine($"Time: {now:t}");  // Outputs: Time: 10:30 AM (short time format)
Console.WriteLine($"Full: {now:F}");  // Outputs: Full: Friday, May 10, 2023 10:30:45 AM
                            

Special Characters

You can include special characters in your output using escape sequences:


// Using escape sequences
Console.WriteLine("Hello\nWorld");  // Outputs Hello and World on separate lines
Console.WriteLine("I am learning \"C#\"");  // Outputs: I am learning "C#"
Console.WriteLine("Path: C:\\Program Files\\App");  // Outputs: Path: C:\Program Files\App

// Using verbatim strings (preceded by @)
Console.WriteLine(@"Path: C:\Program Files\App");  // No need to escape backslashes
Console.WriteLine(@"This is a
multi-line
string");  // Preserves line breaks
                            

Common escape sequences:

  • \n - New line
  • \t - Tab
  • \" - Double quote
  • \' - Single quote
  • \\ - Backslash
  • \r - Carriage return

C# Variables

What is a Variable?

In C#, a variable is a container for storing data values. Variables serve as named memory locations where data can be stored and manipulated during program execution. Each variable has a specific data type that determines what kind of information it can hold.

Basic Variable Declaration:


// Type variableName = value;
int myNum = 5;               // Integer (whole number)
double myDoubleNum = 5.99D;  // Floating point number
char myLetter = 'D';         // Character
bool myBool = true;          // Boolean
string myText = "Hello";     // String
                            

Variable Naming Rules

When naming variables in C#, you must follow these rules:

  • Must start with a letter or underscore (_)
  • Cannot start with a number
  • Cannot contain spaces or special characters like !, @, #, etc.
  • Cannot be a C# keyword (like int, string, class, etc.)
  • Are case-sensitive (age and Age are different variables)

Valid and Invalid Variable Names:


// Valid variable names
int age;
string userName;
double _temperature;
bool isActive;
int totalItems123;

// Invalid variable names
// int 1stNumber;      // Cannot start with a number
// string user-name;   // Cannot contain hyphen
// double class;       // Cannot use C# keywords
// bool my variable;   // Cannot contain spaces
                            

C# Naming Conventions

While not required by the compiler, following these conventions makes your code more readable and maintainable:

  • camelCase for local variables and method parameters (e.g., firstName, totalAmount)
  • PascalCase for class names, method names, and properties (e.g., Customer, CalculateTotal)
  • _camelCase for private fields (e.g., _firstName)
  • ALL_UPPERCASE for constants (e.g., MAX_SIZE, PI)

Variable Declaration and Initialization

In C#, you have several ways to declare and initialize variables:


// Declaration without initialization (default values are assigned)
int count;          // Default value: 0
bool flag;          // Default value: false
string name;        // Default value: null

// Declaration with initialization
int age = 25;
string firstName = "John";

// Multiple declarations of the same type
int x = 10, y = 20, z = 30;

// Using var (type inference) - compiler determines the type based on the value
var total = 100;        // Inferred as int
var message = "Hello";  // Inferred as string
var price = 29.99;      // Inferred as double
var today = DateTime.Now;  // Inferred as DateTime
                            

Note on var:

When using var, the variable must be initialized at the time of declaration, as the compiler needs the initial value to determine the type. Once the type is inferred, it cannot be changed later.

Variable Scope

The scope of a variable determines where in the code the variable is accessible. C# has several levels of scope:

Block Scope:


void ExampleMethod()
{
    // Method-level scope
    int outerVariable = 10;
    
    if (outerVariable > 5)
    {
        // Block-level scope
        int innerVariable = 20;
        Console.WriteLine(outerVariable);    // Can access outerVariable
        Console.WriteLine(innerVariable);    // Can access innerVariable
    }
    
    Console.WriteLine(outerVariable);    // Can access outerVariable
    // Console.WriteLine(innerVariable); // ERROR: Cannot access innerVariable here
}
                            

Class Scope:


class Person
{
    // Class-level fields (accessible throughout the class)
    private string _name;
    private int _age;
    
    // Constructor
    public Person(string name, int age)
    {
        // Constructor parameters (method scope)
        _name = name;  // Assign parameter to field
        _age = age;    // Assign parameter to field
    }
    
    public void DisplayInfo()
    {
        // Local variable (method scope)
        string message = $"Name: {_name}, Age: {_age}";
        Console.WriteLine(message);
    }
}
                            

Constants

Constants are values that cannot be modified after they are declared. They must be initialized at the time of declaration:


// Constants must be assigned a value when declared
const double PI = 3.14159;
const int MAX_USERS = 100;
const string CONNECTION_STRING = "Server=myServerAddress;Database=myDataBase;";

// This will cause a compilation error:
// PI = 3.14; // Constants cannot be changed
                            

When to Use Constants:

Use constants for values that are truly fixed and will never change, such as mathematical constants, fixed configuration values, or fixed business rules. Constants are evaluated at compile time, so they're very efficient.

Read-only Fields

For class-level variables that should be immutable but can be set at runtime (usually in a constructor), use the readonly keyword:


public class Configuration
{
    // Read-only fields - can only be assigned in declaration or constructor
    private readonly string _serverName;
    private readonly int _timeoutSeconds;
    public readonly DateTime CreationTime = DateTime.Now;
    
    public Configuration(string serverName)
    {
        _serverName = serverName;
        _timeoutSeconds = 30; // Can set in constructor
    }
    
    public void ChangeSettings()
    {
        // This would cause a compilation error:
        // _serverName = "newServer"; // Cannot modify readonly fields
    }
}
                            

Working with Variables

Once declared, variables can be manipulated in various ways:

Variable Operations:


// Arithmetic operations
int a = 10;
int b = 3;
int sum = a + b;        // Addition: 13
int difference = a - b; // Subtraction: 7
int product = a * b;    // Multiplication: 30
int quotient = a / b;   // Division: 3 (integer division)
int remainder = a % b;  // Modulus (remainder): 1

// Compound assignment operators
int count = 5;
count += 2;  // Equivalent to: count = count + 2; (count becomes 7)
count -= 1;  // Equivalent to: count = count - 1; (count becomes 6)
count *= 3;  // Equivalent to: count = count * 3; (count becomes 18)
count /= 2;  // Equivalent to: count = count / 2; (count becomes 9)

// Increment and decrement
int x = 10;
x++;  // Increment by 1 (x becomes 11)
x--;  // Decrement by 1 (x becomes 10)

// Pre-increment and post-increment
int y = 5;
int z1 = ++y;  // Pre-increment: y becomes 6, then z1 is assigned 6
int z2 = y++;  // Post-increment: z2 is assigned 6, then y becomes 7
                            

Displaying Variables

There are multiple ways to display variables in C#:

Output Methods:


// String concatenation (using + operator)
string name = "Alice";
int age = 28;
Console.WriteLine("Name: " + name + ", Age: " + age);

// String interpolation (recommended, C# 6.0+)
Console.WriteLine($"Name: {name}, Age: {age}");

// String.Format method
Console.WriteLine(String.Format("Name: {0}, Age: {1}", name, age));

// Composite formatting
Console.WriteLine("Name: {0}, Age: {1}", name, age);

// With formatting options
double price = 123.45;
Console.WriteLine($"Price: {price:C}");  // Currency format: $123.45 (locale-dependent)
Console.WriteLine($"Price: {price:F1}"); // Fixed-point: 123.5 (1 decimal place)
Console.WriteLine($"Tax rate: {0.0825:P}"); // Percentage: 8.25%
                            

Common Pitfalls

  • Uninitialized Variables - Local variables must be initialized before use
  • Variable Shadowing - Declaring a variable inside a block with the same name as a variable in an outer block
  • Confusing Value vs. Reference Types - Understanding how variables store data (by value or by reference)
  • Var Misuse - Using var excessively can make code harder to understand

Variable Shadowing Example:


int x = 10;  // Outer variable

if (true)
{
    int x = 20;  // Inner variable (shadows the outer one)
    Console.WriteLine(x);  // Outputs: 20 (refers to the inner variable)
}

Console.WriteLine(x);  // Outputs: 10 (refers to the outer variable)
                            

Practice with Variables

To practice using variables, try the Beginner C# Course which includes hands-on exercises where you can write and run code.

Test Your Knowledge: Variables

Question 1: Which of the following correctly declares an integer variable named 'count' with a value of 10?

Question 2: What will be the output of the following code?

int x = 5;
int y = 2;
int z = x + y;
Console.WriteLine(z);

Question 3: Which statement about the const keyword is true?

C# Data Types

Introduction to C# Data Types

C# is a strongly-typed language, which means every variable and constant has a specific data type that determines the size and layout of the variable's memory, the range of values that can be stored within that memory, and the set of operations that can be performed on the variable.

C# data types are divided into two main categories:

  • Value Types - Directly contain their data and are stored on the stack
  • Reference Types - Store a reference to their data, which is stored on the heap

Value Types

Value types hold the actual data within their own memory allocation. When you assign one value type to another, a copy of the value is created.

Value Type Behavior:


int a = 10;
int b = a;    // Value is copied, b now has its own copy of 10
a = 20;       // Changing a does not affect b
Console.WriteLine(b);  // Outputs: 10
                            

Common Value Types:

Category Type Size Range Example
Integer Types sbyte 8 bits -128 to 127 sbyte temperature = -10;
byte 8 bits 0 to 255 byte colorValue = 255;
short 16 bits -32,768 to 32,767 short elevation = -1500;
int 32 bits -2.1 billion to 2.1 billion int population = 37500000;
long 64 bits -9.2 quintillion to 9.2 quintillion long nationalDebt = 21000000000000L;
Unsigned Integers ushort 16 bits 0 to 65,535 ushort portNumber = 8080;
uint 32 bits 0 to 4.2 billion uint viewCount = 3000000000U;
ulong 64 bits 0 to 18.4 quintillion ulong distance = 18446744073709551615UL;
Floating Point float 32 bits ±1.5 × 10−45 to ±3.4 × 1038, 7-digit precision float pi = 3.14159F;
double 64 bits ±5.0 × 10−324 to ±1.7 × 10308, 15-16 digit precision double atomRadius = 0.000000001;
Decimal decimal 128 bits ±1.0 × 10-28 to ±7.9 × 1028, 28-29 significant digits decimal accountBalance = 3456.78M;
Boolean bool 8 bits* true or false bool isActive = true;
Character char 16 bits U+0000 to U+FFFF (Unicode characters) char grade = 'A';

* While a boolean logically only needs 1 bit, it typically uses 8 bits (1 byte) of storage due to memory alignment requirements.

Struct Types

Structs are value types that can contain multiple variables (fields), methods, and other members. They are useful for representing lightweight objects.

Custom Struct Example:


// Defining a struct
struct Point
{
    public int X;
    public int Y;
    
    // Constructor
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
    
    // Method
    public double DistanceFromOrigin()
    {
        return Math.Sqrt(X * X + Y * Y);
    }
}

// Using the struct
Point p1 = new Point(3, 4);
Console.WriteLine($"Distance from origin: {p1.DistanceFromOrigin()}");  // Outputs: 5
                            

Enum Types

Enumerations (enums) are distinct value types consisting of a set of named constants. They are useful for representing a fixed set of options or states.

Enum Example:


// Defining an enum
enum DaysOfWeek
{
    Monday,     // 0 by default
    Tuesday,    // 1
    Wednesday,  // 2
    Thursday,   // 3
    Friday,     // 4
    Saturday,   // 5
    Sunday      // 6
}

// Using an enum
DaysOfWeek today = DaysOfWeek.Wednesday;
Console.WriteLine(today);         // Outputs: Wednesday
Console.WriteLine((int)today);    // Outputs: 2

// Enum with explicit values
enum HttpStatusCode
{
    OK = 200,
    NotFound = 404,
    InternalServerError = 500
}

HttpStatusCode status = HttpStatusCode.NotFound;
Console.WriteLine($"Status: {status}, Code: {(int)status}");  // Outputs: Status: NotFound, Code: 404
                            

Reference Types

Reference types store a reference (or pointer) to the actual data in memory. When you assign one reference type to another, both variables refer to the same data.

Reference Type Behavior:


string a = "Hello";
string b = a;       // Both a and b reference the same string
a = "World";        // a now references a new string
Console.WriteLine(b);  // Outputs: Hello (unchanged)

// For objects (classes), changing properties affects all references
Person person1 = new Person { Name = "Alice" };
Person person2 = person1;   // Both reference the same object
person1.Name = "Bob";       // Change affects both references
Console.WriteLine(person2.Name);  // Outputs: Bob
                            

Common Reference Types:

Type Description Example
string Text (sequence of characters) string name = "John Smith";
class User-defined type with members Person employee = new Person();
object Base class for all types object data = 42;
dynamic Type resolved at runtime dynamic value = "test";
interface Contract defining members IEnumerable numbers;
delegate Reference to a method Action log;
array Collection of items int[] numbers = {1, 2, 3};

String Type

The string type represents a sequence of Unicode characters. Strings in C# are immutable, meaning once a string is created, its value cannot be changed.

String Examples:


// String declaration and initialization
string firstName = "John";
string lastName = "Smith";
string emptyString = string.Empty;  // Preferred way to create an empty string

// String concatenation
string fullName = firstName + " " + lastName;  // "John Smith"

// String interpolation (C# 6.0+)
string greeting = $"Hello, {firstName}!";  // "Hello, John!"

// String methods
string message = "   Learn C# Programming   ";
string trimmed = message.Trim();                  // "Learn C# Programming"
string uppercase = message.ToUpper();             // "   LEARN C# PROGRAMMING   "
string replaced = message.Replace("C#", "C++");   // "   Learn C++ Programming   "
bool contains = message.Contains("C#");           // true
int length = message.Length;                      // 27
int index = message.IndexOf("C#");                // 9

// String comparison
bool isEqual = firstName == "John";               // true
bool startsWithJ = firstName.StartsWith("J");     // true
bool ignoreCase = firstName.Equals("john", StringComparison.OrdinalIgnoreCase);  // true

// Verbatim string literal (preserves whitespace and newlines)
string path = @"C:\Program Files\Microsoft\Windows";  // No need to escape backslashes

// String with multiple lines
string multiline = @"This is a
multi-line
string";

// String interpolation with verbatim strings (C# 8.0+)
string combinedPath = $@"C:\Users\{userName}\Documents";
                            

Default Values

When a variable is declared but not initialized, it is assigned a default value based on its data type:

Type Default Value
Numeric types (int, float, etc.) 0 (appropriate for the type)
bool false
char '\0' (null character)
Reference types (string, class types) null
Struct types Each field set to its default value
enum types 0 (the value of the first enumerator)

Default Value Example:


// Explicit default values
int number = default;           // 0
bool flag = default;            // false
string text = default;          // null
double price = default;         // 0.0

// Using default expression (C# 7.1+)
DateTime date = default;        // 01/01/0001 00:00:00
int[] array = default;          // null

// Using default operator
var defaultInt = default(int);    // 0
var defaultBool = default(bool);  // false
var defaultString = default(string);  // null
                            

Special Types

Nullable Value Types

Value types normally cannot be assigned null. However, by using the nullable type decorator (?), value types can be made nullable.


// Regular value type cannot be null
// int regularInt = null;  // Error!

// Nullable value type can be null
int? nullableInt = null;
double? nullableDouble = null;

// Checking for null before using
if (nullableInt.HasValue)
{
    Console.WriteLine(nullableInt.Value);  // Safe to access value
}

// Null coalescing operator to provide a default value
int result = nullableInt ?? 0;  // If nullableInt is null, use 0
                            

var Keyword

The var keyword enables type inference, allowing the compiler to determine the type from the initialization expression.


// Type inference with var
var count = 10;              // Inferred as int
var name = "Alice";          // Inferred as string
var items = new List(); // Inferred as List
var today = DateTime.Now;    // Inferred as DateTime

// Restrictions:
// var must be initialized
// var price;  // Error! Must be initialized

// Type is fixed at compile-time
var number = 5;  // Type is int
// number = "string";  // Error! Cannot assign string to int
                            

dynamic Type

The dynamic type bypasses compile-time type checking. The type checking happens at runtime:


// Dynamic typing
dynamic value = 10;
Console.WriteLine(value);  // 10

value = "Hello";           // Can change type at runtime
Console.WriteLine(value);  // Hello

value = new List { 1, 2, 3 };
Console.WriteLine(value.Count);  // 3

// No compile-time checking
// Only runtime checking for methods/properties
dynamic obj = new { Name = "Test" };
Console.WriteLine(obj.Name);       // Works
// Console.WriteLine(obj.Missing);  // Runtime error!
                            

Type Checking

C# provides several ways to check the type of a variable:

Type Checking Examples:


object obj = "This is a string";

// Using is operator
if (obj is string)
{
    Console.WriteLine("obj is a string");
}

// Using GetType() and typeof
if (obj.GetType() == typeof(string))
{
    Console.WriteLine("obj is of type string");
}

// Using is with pattern matching (C# 7.0+)
if (obj is string message)
{
    // message is now a string variable containing the value of obj
    Console.WriteLine($"Message: {message}");
}

// Using switch expression with pattern matching (C# 8.0+)
string result = obj switch
{
    string s => $"String of length {s.Length}",
    int i => $"Integer: {i}",
    _ => "Unknown type"
};
                            

Best Practices for Working with Types

  • Choose the right type for your data to ensure memory efficiency and prevent overflow/underflow.
  • Use decimal for money calculations to avoid floating-point precision issues.
  • Avoid excessive type casting as it can lead to potential data loss and reduces code readability.
  • Use var when the type is obvious from initialization, but avoid it when clarity is important.
  • Use dynamic sparingly, as it bypasses compile-time type checking and can lead to runtime errors.
  • Consider using nullable types for database interactions where null values may be present.
  • Prefer string interpolation ($"...") over string concatenation for readability.

Test Your Knowledge: Data Types

Question 1: Which of the following is NOT a value type in C#?

Question 2: What is the default value of a boolean variable that has not been initialized?

Question 3: Which data type would be best for storing the precise monetary value $1,234.56?

LINQ (Language Integrated Query)

What is LINQ?

LINQ (Language Integrated Query) allows you to query data from different sources like arrays, collections, XML, and databases using a uniform syntax. It brings the power of SQL-like querying capabilities directly into C#.

Basic LINQ Query:


// Data source
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

// Query syntax
var evenNumbers = from num in numbers
                 where num % 2 == 0
                 select num;

// Method syntax (alternative)
var evenNumbersMethod = numbers.Where(n => n % 2 == 0);

// Display results
foreach (var num in evenNumbers)
{
    Console.WriteLine(num);  // Outputs: 2, 4, 6, 8, 10
}
                            

This example:

  • Creates an array of integers
  • Uses LINQ Query Syntax to filter even numbers
  • Shows the equivalent Method Syntax (alternative)
  • Displays the filtered results

LINQ Operations

LINQ provides numerous operations for data manipulation:

Common LINQ Operations:


List<string> names = new List<string> { "Alice", "Bob", "Charlie", "David", "Emma" };

// Filtering - Get names with length > 4
var longNames = names.Where(name => name.Length > 4);

// Ordering - Sort names alphabetically
var orderedNames = names.OrderBy(name => name);

// Projection - Get lengths of all names
var nameLengths = names.Select(name => name.Length);

// Aggregation - Count, Sum, Average, etc.
int totalChars = names.Sum(name => name.Length);
double averageLength = names.Average(name => name.Length);
int maxLength = names.Max(name => name.Length);

// Grouping - Group by first letter
var nameGroups = names.GroupBy(name => name[0]);
                            

LINQ to Objects

LINQ to Objects is used to query collections that implement IEnumerable<T> like List<T>, Array, Dictionary<TKey, TValue>, etc.

LINQ with Complex Objects:


// Define a class
class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string Category { get; set; }
}

// Create a list of products
List<Product> products = new List<Product>
{
    new Product { Id = 1, Name = "Laptop", Price = 1200, Category = "Electronics" },
    new Product { Id = 2, Name = "Desk Chair", Price = 250, Category = "Furniture" },
    new Product { Id = 3, Name = "Smartphone", Price = 800, Category = "Electronics" },
    new Product { Id = 4, Name = "Bookshelf", Price = 150, Category = "Furniture" },
    new Product { Id = 5, Name = "Headphones", Price = 100, Category = "Electronics" }
};

// Query for electronics under $1000
var affordableElectronics = products
    .Where(p => p.Category == "Electronics" && p.Price < 1000)
    .OrderBy(p => p.Price);

// Group products by category with average price
var productsByCategory = products
    .GroupBy(p => p.Category)
    .Select(g => new {
        Category = g.Key,
        Count = g.Count(),
        AveragePrice = g.Average(p => p.Price)
    });
                            

Test Your Knowledge: LINQ

Question 1: Which LINQ operator is used to filter elements based on a condition?

Question 2: What will the following LINQ query return?

var numbers = new[] { 1, 2, 3, 4, 5 };
var result = numbers.FirstOrDefault(n => n > 10);

Beginner C# Course

Welcome to our interactive C# course for beginners! This course contains 30 progressive exercises that will teach you C# programming from the ground up. Complete the exercises in order to unlock more advanced topics.

0% Complete (0/30)

Module 1: Getting Started with C#

Exercise 1: Hello World

Not Started

Let's start with the classic "Hello World" program. This is often the first program written when learning a new language.

Task: Complete the code below by adding the missing line to display "Hello, World!" to the console.

Hint: Look for the TODO comment and use Console.WriteLine() to output text to the console.

using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            // TODO: Add a line of code here to display "Hello, World!" to the console
            
        }
    }
}
                            
Output:
Code not run yet...
Need a hint?

Replace the TODO comment with this line:

Console.WriteLine("Hello, World!");

Exercise 2: Variables and Output

Locked

Complete previous exercises to unlock this exercise.

Variables are used to store data values. In C#, variables must be declared with a specific data type.

Task: Complete the code by filling in the TODOs:

  1. Create a string variable named name and assign your name to it
  2. Create an integer variable named age and assign your age (or any number) to it
  3. Complete the Console.WriteLine statement to display your name and age
using System;

namespace VariablesAndOutput
{
    class Program
    {
        static void Main(string[] args)
        {
            // TODO 1: Create a string variable named 'name' and assign your name to it
            
            
            // TODO 2: Create an integer variable named 'age' and assign your age to it
            
            
            // TODO 3: Complete the WriteLine statement to display both variables
            Console.WriteLine($"My name is {/* Your code here */} and I am {/* Your code here */} years old.");
        }
    }
}
Output:
Code not run yet...
Need a hint?

Here's how to complete each TODO:

// TODO 1: Create a string variable named 'name' and assign your name to it
string name = "John";

// TODO 2: Create an integer variable named 'age' and assign your age to it
int age = 25;

// TODO 3: Complete the WriteLine statement to display both variables
Console.WriteLine($"My name is {name} and I am {age} years old.");

Exercise 3: Basic Math Operations

Locked

Complete previous exercises to unlock this exercise.

C# supports various arithmetic operations such as addition (+), subtraction (-), multiplication (*), division (/), and modulus (%).

Task: Complete the code by filling in the TODOs to perform basic math operations and display the results.

using System;

namespace MathOperations
{
    class Program
    {
        static void Main(string[] args)
        {
            // Variables are already declared for you
            int a = 10;
            int b = 3;
            
            // TODO 1: Calculate the sum of a and b and store in a variable named 'sum'
            int sum = // Your code here
            
            // TODO 2: Calculate the difference between a and b (a - b) and store in a variable named 'difference'
            int difference = // Your code here
            
            // TODO 3: Calculate the product of a and b and store in a variable named 'product'
            int product = // Your code here
            
            // TODO 4: Calculate the quotient of a divided by b and store in a variable named 'quotient'
            int quotient = // Your code here
            
            // TODO 5: Calculate the remainder when a is divided by b using the modulus operator and store in a variable named 'remainder'
            int remainder = // Your code here
            
            // The code to display the results is already written for you
            Console.WriteLine($"a = {a}, b = {b}");
            Console.WriteLine($"Sum: {sum}");
            Console.WriteLine($"Difference: {difference}");
            Console.WriteLine($"Product: {product}");
            Console.WriteLine($"Quotient: {quotient}");
            Console.WriteLine($"Remainder: {remainder}");
        }
    }
}
Output:
Code not run yet...
Need a hint?

Here's how to perform each math operation:

// TODO 1: Calculate the sum of a and b and store in a variable named 'sum'
int sum = a + b;

// TODO 2: Calculate the difference between a and b (a - b) and store in a variable named 'difference'
int difference = a - b;

// TODO 3: Calculate the product of a and b and store in a variable named 'product'
int product = a * b;

// TODO 4: Calculate the quotient of a divided by b and store in a variable named 'quotient'
int quotient = a / b;

// TODO 5: Calculate the remainder when a is divided by b using the modulus operator and store in a variable named 'remainder'
int remainder = a % b;

Exercise 4: User Input

Locked

Complete previous exercises to unlock this exercise.

Programs often need to get input from users. In C#, we can use Console.ReadLine() to read user input from the console.

Task: Create a program that:

  1. Asks the user to enter their name
  2. Reads the input using Console.ReadLine()
  3. Asks the user to enter their age
  4. Reads the age input and converts it to an integer using int.Parse()
  5. Calculates what year they were born (roughly) by subtracting their age from the current year
  6. Outputs a personalized message with their name and birth year
using System;

namespace UserInput
{
    class Program
    {
        static void Main(string[] args)
        {
            // Get the current year (for simplicity, we'll hardcode it)
            int currentYear = 2023;
            
            // Ask for user's name
            
            // Read the name input
            
            // Ask for user's age
            
            // Read and convert the age input
            
            // Calculate birth year
            
            // Output personalized message
            
        }
    }
}
Output:
Code not run yet...
Need a hint?

Here's how to get user input and convert it:

Console.Write("Enter your name: ");
string name = Console.ReadLine();

Console.Write("Enter your age: ");
int age = int.Parse(Console.ReadLine());

int birthYear = currentYear - age;
Console.WriteLine($"Hello {name}, you were born around {birthYear}.");

Module 2: Control Flow

Exercise 5: If-Else Statements

Locked

Complete previous exercises to unlock this exercise.

Conditional statements allow your program to make decisions based on conditions. The if-else statement is one of the most common control structures.

Task: Create a program that:

  1. Asks the user to enter a number
  2. Checks if the number is positive, negative, or zero
  3. Outputs an appropriate message based on the check
using System;

namespace IfElseDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // Ask for a number
            Console.Write("Enter a number: ");
            
            // Read and convert the input
            int number = int.Parse(Console.ReadLine());
            
            // Check if positive, negative, or zero and output message
            
        }
    }
}
Output:
Code not run yet...
Need a hint?

Use if-else if-else structure to check multiple conditions:

if (number > 0)
{
    Console.WriteLine("The number is positive.");
}
else if (number < 0)
{
    Console.WriteLine("The number is negative.");
}
else
{
    Console.WriteLine("The number is zero.");
}

Exercise 6: For Loops

Locked

Complete previous exercises to unlock this exercise.

Loops allow you to execute a block of code repeatedly. The for loop is useful when you know how many times you need to iterate.

Task: Create a program that:

  1. Asks the user to enter a positive number
  2. Calculates and prints the factorial of that number

Remember: The factorial of a number n (written as n!) is the product of all positive integers less than or equal to n. For example, 5! = 5 × 4 × 3 × 2 × 1 = 120.

using System;

namespace ForLoopFactorial
{
    class Program
    {
        static void Main(string[] args)
        {
            // Ask for a positive number
            Console.Write("Enter a positive number: ");
            int number = int.Parse(Console.ReadLine());
            
            // Initialize factorial
            long factorial = 1;
            
            // Calculate factorial using a for loop
            
            
            // Output the result
            
        }
    }
}
Output:
Code not run yet...
Need a hint?

Use a for loop to multiply the factorial by each number:

for (int i = 1; i <= number; i++)
{
    factorial *= i;  // This is shorthand for: factorial = factorial * i;
}

Console.WriteLine($"The factorial of {number} is {factorial}");

Exercise 7: While Loops

Locked

Complete previous exercises to unlock this exercise.

The while loop executes a block of code as long as a specified condition is true. It's useful when you don't know exactly how many times the loop needs to execute.

Task: Create a program that:

  1. Generates a random number between 1 and 100
  2. Asks the user to guess the number
  3. Tells the user if their guess is too high or too low
  4. Continues until the user guesses correctly
  5. Keeps track of and displays the number of guesses it took
using System;

namespace GuessingGame
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a random number generator
            Random random = new Random();
            
            // Generate a random number between 1 and 100
            int targetNumber = random.Next(1, 101);
            
            // Initialize variables
            int guess = 0;
            int attempts = 0;
            
            // Print welcome message
            Console.WriteLine("I'm thinking of a number between 1 and 100.");
            
            // Main game loop
            
        }
    }
}
Output:
Code not run yet...
Need a hint?

Use a while loop that continues until the guess matches the target:

while (guess != targetNumber)
{
    attempts++;
    Console.Write("Take a guess: ");
    guess = int.Parse(Console.ReadLine());
    
    if (guess < targetNumber)
    {
        Console.WriteLine("Too low!");
    }
    else if (guess > targetNumber)
    {
        Console.WriteLine("Too high!");
    }
}

Console.WriteLine($"Congratulations! You guessed the number in {attempts} attempts.");

Exercise 8: Arrays

Locked

Complete previous exercises to unlock this exercise.

Arrays are used to store multiple values in a single variable. They are a fundamental data structure in C#.

Task: Create a program that:

  1. Creates an array of 5 integers
  2. Asks the user to input 5 numbers and stores them in the array
  3. Calculates and displays the sum, average, minimum, and maximum of the numbers
using System;

namespace ArraysDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create an array to store 5 integers
            int[] numbers = new int[5];
            
            // Ask user to input 5 numbers
            Console.WriteLine("Please enter 5 numbers:");
            
            // Store user input in the array
            
            
            // Calculate sum
            
            
            // Calculate average
            
            
            // Find minimum and maximum
            
            
            // Display results
            
        }
    }
}
Output:
Code not run yet...
Need a hint?

Here's how to work with arrays:

// Get user input
for (int i = 0; i < numbers.Length; i++)
{
    Console.Write($"Enter number {i+1}: ");
    numbers[i] = int.Parse(Console.ReadLine());
}

// Calculate sum
int sum = 0;
for (int i = 0; i < numbers.Length; i++)
{
    sum += numbers[i];
}

// Calculate average
double average = (double)sum / numbers.Length;

// Find min and max
int min = numbers[0];
int max = numbers[0];

for (int i = 1; i < numbers.Length; i++)
{
    if (numbers[i] < min)
        min = numbers[i];
    
    if (numbers[i] > max)
        max = numbers[i];
}

// Display results
Console.WriteLine($"Sum: {sum}");
Console.WriteLine($"Average: {average}");
Console.WriteLine($"Minimum: {min}");
Console.WriteLine($"Maximum: {max}");

Exercise 9: Methods

Locked

Complete previous exercises to unlock this exercise.

Methods (or functions) allow you to reuse code and organize your program into logical blocks. They are essential for writing clean, maintainable code.

Task: Create a program that includes the following methods:

  1. A method called Add that takes two integers as parameters and returns their sum
  2. A method called Subtract that takes two integers and returns their difference
  3. A method called Multiply that takes two integers and returns their product
  4. A method called Divide that takes two integers and returns their quotient as a double
  5. Call each method with test values and display the results
using System;

namespace MethodsDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // Test values
            int a = 10;
            int b = 5;
            
            // Call methods and display results
            
        }
        
        // Define the Add method
        
        
        // Define the Subtract method
        
        
        // Define the Multiply method
        
        
        // Define the Divide method
        
    }
}
Output:
Code not run yet...
Need a hint?

Here's how to define and call methods:

// In Main method
Console.WriteLine($"{a} + {b} = {Add(a, b)}");
Console.WriteLine($"{a} - {b} = {Subtract(a, b)}");
Console.WriteLine($"{a} * {b} = {Multiply(a, b)}");
Console.WriteLine($"{a} / {b} = {Divide(a, b)}");

// Method definitions
static int Add(int x, int y)
{
    return x + y;
}

static int Subtract(int x, int y)
{
    return x - y;
}

static int Multiply(int x, int y)
{
    return x * y;
}

static double Divide(int x, int y)
{
    return (double)x / y;
}

Exercise 10: Simple Calculator

Locked

Complete previous exercises to unlock this exercise.

Let's combine what we've learned to build a simple calculator application.

Task: Create a console calculator that:

  1. Asks the user to enter two numbers
  2. Asks the user to choose an operation (addition, subtraction, multiplication, division)
  3. Performs the selected operation using methods
  4. Displays the result
  5. Asks if the user wants to perform another calculation
  6. Continues until the user chooses to exit
using System;

namespace SimpleCalculator
{
    class Program
    {
        static void Main(string[] args)
        {
            bool continueCalculating = true;
            
            Console.WriteLine("Welcome to Simple Calculator!");
            
            while (continueCalculating)
            {
                // Get first number
                
                
                // Get second number
                
                
                // Get operation choice
                
                
                // Perform calculation
                
                
                // Ask if the user wants to continue
                
            }
            
            Console.WriteLine("Thank you for using Simple Calculator!");
        }
        
        // Addition method
        
        
        // Subtraction method
        
        
        // Multiplication method
        
        
        // Division method
        
    }
}
Output:
Code not run yet...
Need a hint?

Here's an example of a simple calculator implementation:

// Get first number
Console.Write("Enter first number: ");
double num1 = double.Parse(Console.ReadLine());

// Get second number
Console.Write("Enter second number: ");
double num2 = double.Parse(Console.ReadLine());

// Get operation choice
Console.WriteLine("Choose an operation:");
Console.WriteLine("1. Addition (+)");
Console.WriteLine("2. Subtraction (-)");
Console.WriteLine("3. Multiplication (*)");
Console.WriteLine("4. Division (/)");
Console.Write("Enter your choice (1-4): ");
int choice = int.Parse(Console.ReadLine());

// Perform calculation
double result = 0;
switch (choice)
{
    case 1:
        result = Add(num1, num2);
        Console.WriteLine($"{num1} + {num2} = {result}");
        break;
    case 2:
        result = Subtract(num1, num2);
        Console.WriteLine($"{num1} - {num2} = {result}");
        break;
    case 3:
        result = Multiply(num1, num2);
        Console.WriteLine($"{num1} * {num2} = {result}");
        break;
    case 4:
        if (num2 != 0)
        {
            result = Divide(num1, num2);
            Console.WriteLine($"{num1} / {num2} = {result}");
        }
        else
        {
            Console.WriteLine("Error: Cannot divide by zero!");
        }
        break;
    default:
        Console.WriteLine("Invalid choice!");
        break;
}

// Ask if the user wants to continue
Console.Write("Do you want to perform another calculation? (yes/no): ");
string answer = Console.ReadLine().ToLower();
continueCalculating = (answer == "yes" || answer == "y");

Module 3: Object-Oriented Programming

Exercise 11: Classes and Objects

Locked

Complete previous exercises to unlock this exercise.

Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects". In C#, classes are used to define objects.

Task: Create a program that:

  1. Defines a Person class with properties for name, age, and email
  2. Includes a constructor to initialize these properties
  3. Adds a method called DisplayInfo that prints the person's information
  4. Creates at least two Person objects with different values
  5. Calls the DisplayInfo method on each object
using System;

namespace ClassesAndObjects
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create Person objects
            
            
            // Display their information
            
        }
    }
    
    // Define the Person class
    
}
Output:
Code not run yet...
Need a hint?

Here's how to define a class with properties, a constructor, and methods:

// In Main method
Person person1 = new Person("John Doe", 30, "john@example.com");
Person person2 = new Person("Jane Smith", 25, "jane@example.com");

person1.DisplayInfo();
person2.DisplayInfo();

// Person class definition
class Person
{
    // Properties
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
    
    // Constructor
    public Person(string name, int age, string email)
    {
        Name = name;
        Age = age;
        Email = email;
    }
    
    // Method to display information
    public void DisplayInfo()
    {
        Console.WriteLine($"Name: {Name}");
        Console.WriteLine($"Age: {Age}");
        Console.WriteLine($"Email: {Email}");
        Console.WriteLine(); // Empty line for spacing
    }
}

Exercise 12: Lists and LINQ

Locked

Complete previous exercises to unlock this exercise.

Lists are dynamic collections that can grow or shrink in size. LINQ (Language Integrated Query) provides a convenient way to query and manipulate collections.

Task: Create a program that:

  1. Creates a List<int> and adds at least 10 random numbers between 1 and 100
  2. Uses LINQ to find and display all even numbers from the list
  3. Uses LINQ to sort the list in descending order and display it
  4. Uses LINQ to find and display the top 3 largest numbers
  5. Uses LINQ to calculate and display the average of all numbers
using System;
using System.Collections.Generic;
using System.Linq;

namespace ListsAndLinq
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a list to store random numbers
            List numbers = new List();
            
            // Create a random number generator
            Random random = new Random();
            
            // Add 10 random numbers between 1 and 100
            for (int i = 0; i < 10; i++)
            {
                numbers.Add(random.Next(1, 101));
            }
            
            // Display the original list
            Console.WriteLine("Original list of numbers:");
            foreach (int num in numbers)
            {
                Console.Write($"{num} ");
            }
            Console.WriteLine("\n");
            
            // Find and display even numbers
            
            
            // Sort and display in descending order
            
            
            // Find and display top 3 largest numbers
            
            
            // Calculate and display the average
            
        }
    }
}
Output:
Code not run yet...
Need a hint?

Here's how to use LINQ for different operations:

// Find and display even numbers
var evenNumbers = numbers.Where(n => n % 2 == 0);
Console.WriteLine("Even numbers:");
foreach (int num in evenNumbers)
{
    Console.Write($"{num} ");
}
Console.WriteLine("\n");

// Sort and display in descending order
var descendingOrder = numbers.OrderByDescending(n => n);
Console.WriteLine("Numbers in descending order:");
foreach (int num in descendingOrder)
{
    Console.Write($"{num} ");
}
Console.WriteLine("\n");

// Find and display top 3 largest numbers
var top3 = numbers.OrderByDescending(n => n).Take(3);
Console.WriteLine("Top 3 largest numbers:");
foreach (int num in top3)
{
    Console.Write($"{num} ");
}
Console.WriteLine("\n");

// Calculate and display the average
double average = numbers.Average();
Console.WriteLine($"Average of all numbers: {average:F2}");

Exercise 13: Exception Handling

Locked

Complete previous exercises to unlock this exercise.

Exception handling allows your program to gracefully handle errors instead of crashing. It's a crucial aspect of writing robust code.

Task: Create a program that:

  1. Asks the user to enter a number
  2. Uses try-catch blocks to handle potential exceptions
  3. Catches and displays appropriate messages for different exception types
  4. Continues asking until the user enters a valid number
  5. Calculates and displays the square root of the number
using System;

namespace ExceptionHandling
{
    class Program
    {
        static void Main(string[] args)
        {
            bool validInput = false;
            double number = 0;
            
            Console.WriteLine("Exception Handling Example");
            
            while (!validInput)
            {
                Console.Write("Enter a positive number: ");
                string input = Console.ReadLine();
                
                // Try to parse the input and calculate square root
                // Handle exceptions appropriately
                
            }
            
            // Calculate and display square root
            
        }
    }
}
Output:
Code not run yet...
Need a hint?

Here's how to implement exception handling:

try
{
    number = double.Parse(input);
    
    if (number < 0)
    {
        Console.WriteLine("Error: Please enter a positive number.");
        continue;
    }
    
    validInput = true;
}
catch (FormatException)
{
    Console.WriteLine("Error: Please enter a valid numeric value.");
}
catch (OverflowException)
{
    Console.WriteLine("Error: The number is too large or too small.");
}
catch (Exception ex)
{
    Console.WriteLine($"An unexpected error occurred: {ex.Message}");
}

// Calculate and display square root (outside the while loop)
double squareRoot = Math.Sqrt(number);
Console.WriteLine($"The square root of {number} is {squareRoot:F4}");

Exercise 14: File Handling

Locked

Complete previous exercises to unlock this exercise.

C# provides various ways to work with files and directories. File handling is essential for many real-world applications.

Task: Create a program that:

  1. Creates a text file named "notes.txt"
  2. Asks the user to enter some text
  3. Writes the user's input to the file
  4. Reads and displays the contents of the file
  5. Appends additional text to the file
  6. Reads and displays the updated contents
using System;
using System.IO;

namespace FileHandling
{
    class Program
    {
        static void Main(string[] args)
        {
            string fileName = "notes.txt";
            
            Console.WriteLine("File Handling Example");
            
            // Ask the user for input
            Console.WriteLine("Enter some text to write to the file:");
            string userInput = Console.ReadLine();
            
            // Create and write to the file
            
            
            // Read and display the file contents
            
            
            // Append additional text
            Console.WriteLine("\nEnter additional text to append to the file:");
            string additionalText = Console.ReadLine();
            
            
            // Read and display the updated content
            
        }
    }
}
Output:
Code not run yet...
Need a hint?

Here's how to handle files in C#:

// Create and write to the file
try
{
    // Write text to the file (overwrites any existing content)
    File.WriteAllText(fileName, userInput);
    Console.WriteLine("File created and text written successfully!");
    
    // Read and display the file contents
    Console.WriteLine("\nFile contents:");
    string fileContent = File.ReadAllText(fileName);
    Console.WriteLine(fileContent);
    
    // Append additional text
    File.AppendAllText(fileName, "\n" + additionalText);
    Console.WriteLine("\nAdditional text appended successfully!");
    
    // Read and display the updated content
    Console.WriteLine("\nUpdated file contents:");
    string updatedContent = File.ReadAllText(fileName);
    Console.WriteLine(updatedContent);
}
catch (Exception ex)
{
    Console.WriteLine($"An error occurred: {ex.Message}");
}

Module 4: Advanced C# Programming

Exercise 15: Inheritance

Locked

Inheritance is a fundamental concept in object-oriented programming that allows a class to inherit properties and methods from another class.

Task: Create a program that:

  1. Defines a base class called Shape with properties for name and color
  2. Adds a virtual method called CalculateArea that returns 0.0
  3. Creates two derived classes: Circle and Rectangle
  4. Overrides the CalculateArea method in each derived class
  5. Creates instances of both classes and calculates their areas
using System;

namespace InheritanceDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create instances of Circle and Rectangle
            
            
            // Display information about the shapes
            
        }
    }
    
    // Define the Shape base class
    
    
    // Define the Circle class
    
    
    // Define the Rectangle class
    
}
Output:
Code not run yet...
Need a hint?

Here's how to implement inheritance:

// In Main method
Circle circle = new Circle("My Circle", "Red", 5.0);
Rectangle rectangle = new Rectangle("My Rectangle", "Blue", 4.0, 6.0);

Console.WriteLine($"Shape: {circle.Name}, Color: {circle.Color}");
Console.WriteLine($"Area: {circle.CalculateArea()}");
Console.WriteLine();

Console.WriteLine($"Shape: {rectangle.Name}, Color: {rectangle.Color}");
Console.WriteLine($"Area: {rectangle.CalculateArea()}");

// Shape base class
class Shape
{
    public string Name { get; set; }
    public string Color { get; set; }
    
    public Shape(string name, string color)
    {
        Name = name;
        Color = color;
    }
    
    public virtual double CalculateArea()
    {
        return 0.0;
    }
}

// Circle class
class Circle : Shape
{
    public double Radius { get; set; }
    
    public Circle(string name, string color, double radius) : base(name, color)
    {
        Radius = radius;
    }
    
    public override double CalculateArea()
    {
        return Math.PI * Radius * Radius;
    }
}

// Rectangle class
class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }
    
    public Rectangle(string name, string color, double width, double height) : base(name, color)
    {
        Width = width;
        Height = height;
    }
    
    public override double CalculateArea()
    {
        return Width * Height;
    }
}

Exercise 16: Interfaces

Locked

Interfaces define a contract that classes can implement. They allow for polymorphism and are a key component of object-oriented design.

Task: Create a program that:

  1. Defines an interface called IDrawable with a method Draw()
  2. Creates three classes that implement the interface: Circle, Rectangle, and Triangle
  3. Implements the Draw() method differently in each class
  4. Creates a list of IDrawable objects with instances of each class
  5. Iterates through the list and calls Draw() on each object
using System;
using System.Collections.Generic;

namespace InterfacesDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a list of IDrawable objects
            
            
            // Add instances of each shape to the list
            
            
            // Draw all shapes
            
        }
    }
    
    // Define the IDrawable interface
    
    
    // Implement Circle class
    
    
    // Implement Rectangle class
    
    
    // Implement Triangle class
    
}
Output:
Code not run yet...
Need a hint?

Here's how to implement interfaces:

// In Main method
List shapes = new List();

shapes.Add(new Circle());
shapes.Add(new Rectangle());
shapes.Add(new Triangle());

Console.WriteLine("Drawing all shapes:");
foreach (IDrawable shape in shapes)
{
    shape.Draw();
}

// Define the interface
interface IDrawable
{
    void Draw();
}

// Circle class
class Circle : IDrawable
{
    public void Draw()
    {
        Console.WriteLine("Drawing a circle: O");
    }
}

// Rectangle class
class Rectangle : IDrawable
{
    public void Draw()
    {
        Console.WriteLine("Drawing a rectangle: □");
    }
}

// Triangle class
class Triangle : IDrawable
{
    public void Draw()
    {
        Console.WriteLine("Drawing a triangle: △");
    }
}

Exercise 17: Generics

Locked

Generics allow you to write type-safe code without committing to specific data types. They increase code reusability and type safety.

Task: Create a program that:

  1. Defines a generic class called Stack<T> that represents a simple stack data structure
  2. Implements methods: Push(T item), Pop(), Peek(), and IsEmpty()
  3. Creates two stacks: one for integers and one for strings
  4. Demonstrates each method on both stacks
using System;
using System.Collections.Generic;

namespace GenericsDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a stack of integers
            
            
            // Push items onto the integer stack
            
            
            // Create a stack of strings
            
            
            // Push items onto the string stack
            
            
            // Demonstrate operations on both stacks
            
        }
    }
    
    // Define the generic Stack class
    
}
Output:
Code not run yet...
Need a hint?

Here's how to implement a generic Stack class:

// In Main method
Stack intStack = new Stack();
Console.WriteLine("Integer Stack Demo:");
Console.WriteLine($"Is empty: {intStack.IsEmpty()}");

intStack.Push(10);
intStack.Push(20);
intStack.Push(30);

Console.WriteLine($"Peek: {intStack.Peek()}");
Console.WriteLine($"Pop: {intStack.Pop()}");
Console.WriteLine($"Peek after pop: {intStack.Peek()}");
Console.WriteLine($"Is empty: {intStack.IsEmpty()}");

Console.WriteLine();

Stack stringStack = new Stack();
Console.WriteLine("String Stack Demo:");

stringStack.Push("Hello");
stringStack.Push("World");
stringStack.Push("C#");

Console.WriteLine($"Peek: {stringStack.Peek()}");
Console.WriteLine($"Pop: {stringStack.Pop()}");
Console.WriteLine($"Peek after pop: {stringStack.Peek()}");

// Generic Stack class
class Stack
{
    private List items = new List();
    
    public void Push(T item)
    {
        items.Add(item);
    }
    
    public T Pop()
    {
        if (IsEmpty())
        {
            throw new InvalidOperationException("Stack is empty");
        }
        
        T item = items[items.Count - 1];
        items.RemoveAt(items.Count - 1);
        return item;
    }
    
    public T Peek()
    {
        if (IsEmpty())
        {
            throw new InvalidOperationException("Stack is empty");
        }
        
        return items[items.Count - 1];
    }
    
    public bool IsEmpty()
    {
        return items.Count == 0;
    }
}

Exercise 18: Delegates and Events

Locked

Delegates enable event-driven programming in C#. They're type-safe function pointers that allow methods to be passed as parameters.

Task: Create a program that:

  1. Defines a delegate called MathOperation that takes two integers and returns an integer
  2. Creates several methods that match the delegate signature (Add, Subtract, Multiply, Divide)
  3. Defines a class Calculator with an event that triggers when an operation is performed
  4. Subscribes to the event and displays messages when operations are performed
  5. Demonstrates using the delegate and event with different operations
using System;

namespace DelegatesAndEvents
{
    // Define the delegate
    
    
    // Define an event args class to pass operation information
    
    
    class Program
    {
        static void Main(string[] args)
        {
            // Create a calculator
            
            
            // Subscribe to the calculator's event
            
            
            // Perform different operations
            
        }
        
        // Define math operation methods
        
    }
    
    // Calculator class with an event
    
}
Output:
Code not run yet...
Need a hint?

Here's how to implement delegates and events:

// Define the delegate
delegate int MathOperation(int x, int y);

// Define an event args class to pass operation information
class CalculatorEventArgs : EventArgs
{
    public string OperationName { get; set; }
    public int Result { get; set; }
    
    public CalculatorEventArgs(string operationName, int result)
    {
        OperationName = operationName;
        Result = result;
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Create a calculator
        Calculator calculator = new Calculator();
        
        // Subscribe to the calculator's event
        calculator.OperationPerformed += Calculator_OperationPerformed;
        
        // Perform different operations
        Console.WriteLine("Addition: " + calculator.PerformOperation(Add, 10, 5, "Addition"));
        Console.WriteLine("Subtraction: " + calculator.PerformOperation(Subtract, 10, 5, "Subtraction"));
        Console.WriteLine("Multiplication: " + calculator.PerformOperation(Multiply, 10, 5, "Multiplication"));
        Console.WriteLine("Division: " + calculator.PerformOperation(Divide, 10, 5, "Division"));
    }
    
    // Event handler method
    static void Calculator_OperationPerformed(object sender, CalculatorEventArgs e)
    {
        Console.WriteLine($"[Event] {e.OperationName} operation performed. Result: {e.Result}");
    }
    
    // Define math operation methods
    static int Add(int x, int y) => x + y;
    static int Subtract(int x, int y) => x - y;
    static int Multiply(int x, int y) => x * y;
    static int Divide(int x, int y) => x / y;
}

// Calculator class with an event
class Calculator
{
    // Define the event
    public event EventHandler OperationPerformed;
    
    // Method to perform operation and raise the event
    public int PerformOperation(MathOperation operation, int x, int y, string operationName)
    {
        int result = operation(x, y);
        
        // Raise the event
        OnOperationPerformed(new CalculatorEventArgs(operationName, result));
        
        return result;
    }
    
    // Method to raise the event
    protected virtual void OnOperationPerformed(CalculatorEventArgs e)
    {
        OperationPerformed?.Invoke(this, e);
    }
}

Exercise 19: LINQ Basics

Locked

LINQ (Language Integrated Query) allows you to query data from different sources using a consistent syntax. It's a powerful feature for data manipulation.

Task: Create a program that:

  1. Creates a list of Person objects with various attributes (name, age, city)
  2. Uses LINQ queries to filter, sort, and project data from the list
  3. Demonstrates both query syntax and method syntax
  4. Includes at least 5 different LINQ operations (Where, OrderBy, Select, GroupBy, etc.)
using System;
using System.Collections.Generic;
using System.Linq;

namespace LinqBasics
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a list of Person objects
            
            
            // LINQ Query 1: Filter people by age (older than 30)
            
            
            // LINQ Query 2: Sort people by name
            
            
            // LINQ Query 3: Project data to a new format
            
            
            // LINQ Query 4: Group people by city
            
            
            // LINQ Query 5: Aggregate data to get statistics
            
        }
    }
    
    // Define the Person class
    
}
Output:
Code not run yet...
Need a hint?

Here's how to use LINQ for different operations:

// Person class
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string City { get; set; }
    
    public Person(string name, int age, string city)
    {
        Name = name;
        Age = age;
        City = city;
    }
}

// In Main method
List people = new List
{
    new Person("Alice", 25, "New York"),
    new Person("Bob", 32, "Chicago"),
    new Person("Charlie", 35, "New York"),
    new Person("David", 28, "Boston"),
    new Person("Eva", 41, "Chicago"),
    new Person("Frank", 22, "Boston"),
    new Person("Grace", 38, "New York")
};

// LINQ Query 1: Filter people by age (older than 30) - Query syntax
Console.WriteLine("People older than 30 (Query syntax):");
var olderPeople = from person in people
                 where person.Age > 30
                 select person;

foreach (var person in olderPeople)
{
    Console.WriteLine($"{person.Name}, {person.Age}");
}
Console.WriteLine();

// LINQ Query 2: Sort people by name - Method syntax
Console.WriteLine("People sorted by name (Method syntax):");
var sortedPeople = people.OrderBy(p => p.Name);

foreach (var person in sortedPeople)
{
    Console.WriteLine($"{person.Name}, {person.Age}");
}
Console.WriteLine();

// LINQ Query 3: Project data to a new format
Console.WriteLine("Name and city only:");
var nameAndCity = people.Select(p => new { p.Name, p.City });

foreach (var item in nameAndCity)
{
    Console.WriteLine($"{item.Name} - {item.City}");
}
Console.WriteLine();

// LINQ Query 4: Group people by city
Console.WriteLine("People grouped by city:");
var groupedByCity = people.GroupBy(p => p.City);

foreach (var cityGroup in groupedByCity)
{
    Console.WriteLine($"City: {cityGroup.Key}");
    foreach (var person in cityGroup)
    {
        Console.WriteLine($"  {person.Name}, {person.Age}");
    }
}
Console.WriteLine();

// LINQ Query 5: Aggregate data to get statistics
Console.WriteLine("Statistics:");
double averageAge = people.Average(p => p.Age);
int minAge = people.Min(p => p.Age);
int maxAge = people.Max(p => p.Age);
var cityCounts = people.GroupBy(p => p.City)
                       .Select(g => new { City = g.Key, Count = g.Count() });

Console.WriteLine($"Average Age: {averageAge:F1}");
Console.WriteLine($"Minimum Age: {minAge}");
Console.WriteLine($"Maximum Age: {maxAge}");
Console.WriteLine("People per city:");
foreach (var city in cityCounts)
{
    Console.WriteLine($"  {city.City}: {city.Count}");
}

Exercise 20: Asynchronous Programming

Locked

Asynchronous programming allows operations to run in the background without blocking the main thread. It's essential for creating responsive applications.

Task: Create a program that:

  1. Defines several async methods that simulate long-running operations
  2. Uses the async and await keywords to call these methods
  3. Demonstrates both sequential and parallel execution of async operations
  4. Shows how to handle exceptions in async code
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace AsyncDemo
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("Asynchronous Programming Demo");
            Console.WriteLine("Starting at: " + DateTime.Now);
            
            // Call async method sequentially
            
            
            // Call async methods in parallel
            
            
            // Demonstrate exception handling in async code
            
        }
        
        // Define async methods
        
    }
}

Congratulations!

You've completed all 20 exercises in the Beginner C# Course! You should now have a solid foundation in C# programming concepts and be ready to tackle more advanced topics.

Consider moving on to the Intermediate C# Course to further enhance your skills.