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 CourseObject-Oriented Programming
Master object-oriented programming principles with C# classes, inheritance, polymorphism, and more.
Learn OOPQuick 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 functionalitynamespace HelloWorld
- Creates a container for your codeclass Program
- Defines a class to hold your methodsstatic void Main(string[] args)
- The entry point of your programConsole.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:
- Visit Visual Studio website
- Download Visual Studio Community (free) or other editions
- Run the installer and select ".NET desktop development" workload
- 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:
- Download and install Visual Studio Code
- Install the C# extension from the marketplace
- 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:
- Open Visual Studio
- Click "Create a new project"
- Select "Console App (.NET Core)" or "Console App (.NET Framework)"
- 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 classnamespace 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 programConsole.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 lineConsole.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 |
delegate |
Reference to a method | Action |
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.
Module 1: Getting Started with C#
Exercise 1: Hello World
Not StartedLet'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
LockedVariables 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:
- Create a string variable named
name
and assign your name to it - Create an integer variable named
age
and assign your age (or any number) to it - 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
LockedC# 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
LockedPrograms 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:
- Asks the user to enter their name
- Reads the input using
Console.ReadLine()
- Asks the user to enter their age
- Reads the age input and converts it to an integer using
int.Parse()
- Calculates what year they were born (roughly) by subtracting their age from the current year
- 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
LockedConditional 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:
- Asks the user to enter a number
- Checks if the number is positive, negative, or zero
- 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
LockedLoops 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:
- Asks the user to enter a positive number
- 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
LockedThe 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:
- Generates a random number between 1 and 100
- Asks the user to guess the number
- Tells the user if their guess is too high or too low
- Continues until the user guesses correctly
- 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
LockedArrays are used to store multiple values in a single variable. They are a fundamental data structure in C#.
Task: Create a program that:
- Creates an array of 5 integers
- Asks the user to input 5 numbers and stores them in the array
- 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
LockedMethods (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:
- A method called
Add
that takes two integers as parameters and returns their sum - A method called
Subtract
that takes two integers and returns their difference - A method called
Multiply
that takes two integers and returns their product - A method called
Divide
that takes two integers and returns their quotient as a double - 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
LockedLet's combine what we've learned to build a simple calculator application.
Task: Create a console calculator that:
- Asks the user to enter two numbers
- Asks the user to choose an operation (addition, subtraction, multiplication, division)
- Performs the selected operation using methods
- Displays the result
- Asks if the user wants to perform another calculation
- 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
LockedObject-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:
- Defines a
Person
class with properties for name, age, and email - Includes a constructor to initialize these properties
- Adds a method called
DisplayInfo
that prints the person's information - Creates at least two Person objects with different values
- 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
LockedLists 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:
- Creates a
List<int>
and adds at least 10 random numbers between 1 and 100 - Uses LINQ to find and display all even numbers from the list
- Uses LINQ to sort the list in descending order and display it
- Uses LINQ to find and display the top 3 largest numbers
- 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
LockedException 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:
- Asks the user to enter a number
- Uses try-catch blocks to handle potential exceptions
- Catches and displays appropriate messages for different exception types
- Continues asking until the user enters a valid number
- 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
LockedC# provides various ways to work with files and directories. File handling is essential for many real-world applications.
Task: Create a program that:
- Creates a text file named "notes.txt"
- Asks the user to enter some text
- Writes the user's input to the file
- Reads and displays the contents of the file
- Appends additional text to the file
- 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
LockedInheritance 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:
- Defines a base class called
Shape
with properties for name and color - Adds a virtual method called
CalculateArea
that returns 0.0 - Creates two derived classes:
Circle
andRectangle
- Overrides the
CalculateArea
method in each derived class - 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
LockedInterfaces 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:
- Defines an interface called
IDrawable
with a methodDraw()
- Creates three classes that implement the interface:
Circle
,Rectangle
, andTriangle
- Implements the
Draw()
method differently in each class - Creates a list of
IDrawable
objects with instances of each class - 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
LockedGenerics 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:
- Defines a generic class called
Stack<T>
that represents a simple stack data structure - Implements methods:
Push(T item)
,Pop()
,Peek()
, andIsEmpty()
- Creates two stacks: one for integers and one for strings
- 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
LockedDelegates 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:
- Defines a delegate called
MathOperation
that takes two integers and returns an integer - Creates several methods that match the delegate signature (Add, Subtract, Multiply, Divide)
- Defines a class
Calculator
with an event that triggers when an operation is performed - Subscribes to the event and displays messages when operations are performed
- 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
LockedLINQ (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:
- Creates a list of
Person
objects with various attributes (name, age, city) - Uses LINQ queries to filter, sort, and project data from the list
- Demonstrates both query syntax and method syntax
- 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
LockedAsynchronous 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:
- Defines several async methods that simulate long-running operations
- Uses the
async
andawait
keywords to call these methods - Demonstrates both sequential and parallel execution of async operations
- 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.