๐ป CSharp-Basics
๐ฉโ๐ป This repository holds common C# syntax, concepts, and examples for beginners and intermediate developers. Whether you're coming from JavaScript, Python, or starting fresh, this guide will help you master C# fundamentals.
๐ฅ๏ธ System Requirements
Download and install the following software:
| Software | Description | Download Link |
|---|---|---|
| .NET SDK | The runtime and compiler for C# | Download .NET |
| VS Code | Lightweight code editor | Download VS Code |
| C# Dev Kit | VS Code extension for C# | Get Extension |
Alternative: Use Visual Studio Community (free, all-in-one IDE)
๐ Getting Started
- Fork and clone this repository
- Open the folder in VS Code or Visual Studio
- Open the terminal (Ctrl + ` in VS Code)
-
Run the examples:
bash dotnet run -
Edit
Program.csto uncomment different example methods - Repeat to explore each concept!
๐ TABLE OF CONTENTS
| Section | Description |
|---|---|
| Introduction | What is C# and why learn it? |
| Variables | Storing and naming data |
| Data Types | Value types vs Reference types |
| Operators | Arithmetic, comparison, logical |
| Type Casting | Converting between types |
| Functions | Creating reusable code blocks |
| Arrays & Collections | Storing multiple values |
| Conditionals | Making decisions in code |
| Loops | Repeating code |
| Exception Handling | Handling errors gracefully |
| Classes | Object-oriented programming |
| Properties | Getters, setters, encapsulation |
| Inheritance | Extending classes |
| Interfaces | Defining contracts |
| Generics | Type-safe reusable code |
| LINQ | Querying data elegantly |
| Async/Await | Asynchronous programming |
| Calculator | Practical exercise |
๐ Introduction
What is C#?
C# (pronounced "C-Sharp") is a modern, object-oriented programming language developed by Microsoft in 2000 as part of its .NET initiative. It was designed by Anders Hejlsberg (who also created Turbo Pascal and TypeScript).
Why Learn C#?
C# is one of the most versatile and in-demand programming languages:
| Use Case | Technology | Examples |
|---|---|---|
| ๐ Web Development | ASP.NET Core | APIs, Web Apps, Microservices |
| ๐ฎ Game Development | Unity | Mobile games, VR/AR, AAA titles |
| ๐ฅ๏ธ Desktop Apps | WPF, WinForms, MAUI | Windows applications |
| ๐ฑ Mobile Apps | .NET MAUI, Xamarin | iOS and Android apps |
| โ๏ธ Cloud Services | Azure Functions | Serverless, cloud-native apps |
| ๐ค AI/ML | ML.NET | Machine learning models |
C# vs JavaScript Comparison
If you're coming from JavaScript, here's a quick comparison:
| Feature | JavaScript | C# |
|---|---|---|
| Typing | Dynamic (let x = 5) |
Static (int x = 5) |
| Execution | Interpreted | Compiled |
| Semicolons | Optional | Required |
| Classes | Prototype-based | Class-based |
| Null handling |
null/undefined
|
null only (with nullable types) |
Your First C# Program
Every C# program starts with a Main method - this is the entry point where your program begins executing:
`csharp
using System; // Import the System namespace (like 'import' in JS)
namespace MyFirstApp // Namespace organizes your code (like a folder)
{
class Program // A class is a container for your code
{
static void Main(string[] args) // Entry point - program starts here
{
Console.WriteLine("Hello, World!"); // Print to console
}
}
}
`
Breaking it down:
-
using System;- Imports built-in functionality (likeimportin JS/Python) -
namespace- Groups related classes together (prevents naming conflicts) -
class- A blueprint/container for code and data -
static void Main()- The entry point;staticmeans no object needed,voidmeans no return value -
Console.WriteLine()- Prints text to the terminal
๐ก Modern C# Tip: In .NET 6+, you can use "top-level statements" for simpler programs:
csharp
Console.WriteLine("Hello, World!");
๐ค Variables
What is a Variable?
A variable is a named container that stores a value in your computer's memory. Think of it like a labeled box where you can put data and retrieve it later.
โโโโโโโโโโโโโโโโโโโ
โ Variable: age โ โโโ The label (name)
โโโโโโโโโโโโโโโโโโโค
โ 25 โ โโโ The value stored inside
โโโโโโโโโโโโโโโโโโโ
Declaring Variables in C
Unlike JavaScript, C# is statically typed - you must declare the type of data a variable will hold:
`csharp
// Syntax: type variableName = value;
string bunnyName = "Lucy"; // Text data (sequence of characters)
int age = 3; // Whole numbers (no decimals)
double weight = 2.5; // Decimal numbers (high precision)
bool isHappy = true; // True or false only
// Print all variables using string interpolation ($"...")
Console.WriteLine($"Name: {bunnyName}, Age: {age}, Weight: {weight}kg, Happy: {isHappy}");
// Output: Name: Lucy, Age: 3, Weight: 2.5kg, Happy: True
`
Why static typing?
- โ Catches errors at compile time (before running)
- โ Better IDE autocomplete and IntelliSense
- โ More efficient memory usage
- โ Self-documenting code
Variable Naming Rules
C# has strict rules for naming variables:
| Rule | Valid โ | Invalid โ | Why? |
|---|---|---|---|
Must start with letter or _
|
name, _count
|
1name |
Numbers can't be first |
Can contain letters, digits, _
|
user1, total_count
|
user-name |
Hyphens not allowed |
| Case-sensitive |
Name โ name
|
- | They're different variables |
| No reserved keywords | myClass |
class, int
|
These are C# keywords |
`csharp
// โ
Valid variable names
string firstName = "Lucy";
string _privateField = "hidden";
int player1Score = 100;
string camelCaseIsPreferred = "yes";
// โ Invalid - these will cause compiler errors
// string 1stPlace = "Gold"; // Can't start with number
// string my-variable = "oops"; // Hyphens not allowed
// string class = "reserved"; // 'class' is a keyword
`
Naming Conventions
C# developers follow specific conventions:
| Type | Convention | Example |
|---|---|---|
| Local variables | camelCase |
firstName, totalCount
|
| Class names | PascalCase |
BunnyManager, PlayerController
|
| Methods | PascalCase |
CalculateTotal(), GetUserName()
|
| Constants | UPPER_CASE or PascalCase |
MAX_SIZE, DefaultTimeout
|
| Private fields | _camelCase |
_connectionString, _logger
|
var, const, and readonly
C# offers three important keywords for variable declaration:
var - Type Inference
The compiler automatically determines the type based on the assigned value:
`csharp
var name = "Lucy"; // Compiler infers: string
var age = 25; // Compiler infers: int
var price = 19.99; // Compiler infers: double
var isActive = true; // Compiler infers: bool
// var MUST be initialized - the compiler needs a value to infer the type
// var unknown; // โ Error: Implicitly-typed variables must be initialized
`
When to use var:
- โ
When the type is obvious:
var list = new List<string>(); - โ
With LINQ queries:
var results = users.Where(u => u.Age > 18); - โ When it reduces readability:
var x = GetData();(what type is x?)
const - Compile-Time Constants
Values that are known at compile time and never change:
`csharp
const double PI = 3.14159265359; // Mathematical constant
const int MAX_PLAYERS = 100; // Game configuration
const string APP_NAME = "BunnyTracker"; // Application name
// Constants MUST be assigned at declaration
// const int laterValue; // โ Error
// Constants CANNOT be changed
// PI = 3.14; // โ Error: Cannot assign to const
`
Key points:
- Value must be known at compile time
- Implicitly
static(shared across all instances) - Can only be primitive types or strings
readonly - Runtime Constants
Values set once at runtime (in declaration or constructor):
`csharp
public class GameConfig
{
// Can be set at declaration
public readonly DateTime CreatedAt = DateTime.Now;
// Or set in constructor
public readonly string ConnectionString;
public GameConfig(string connString)
{
ConnectionString = connString; // โ
Can assign in constructor
}
public void TryChange()
{
// ConnectionString = "new"; // โ Error: Cannot assign after construction
}
}
`
const vs readonly Summary:
| Feature | const |
readonly |
|---|---|---|
| When assigned | Compile time | Runtime (declaration or constructor) |
| Can use expressions | No | Yes (= DateTime.Now) |
| Memory | Stored in assembly | Stored in memory |
| Can be any type | Primitives/strings only | Any type |
Variable Scope
Scope determines where a variable can be accessed in your code:
`csharp
class Program
{
// 1. CLASS-LEVEL (Field) - Accessible anywhere in the class
static string globalBunny = "Lucy";
static void Main()
{
Console.WriteLine(globalBunny); // โ
Works - class-level scope
// 2. METHOD-LEVEL (Local) - Only accessible within this method
string localBunny = "Tom";
Console.WriteLine(localBunny); // โ
Works - same method
if (true)
{
// 3. BLOCK-LEVEL - Only accessible within these braces { }
string blockBunny = "Molly";
Console.WriteLine(blockBunny); // โ
Works - same block
Console.WriteLine(localBunny); // โ
Works - outer scope
}
// Console.WriteLine(blockBunny); // โ Error - out of scope!
}
static void AnotherMethod()
{
Console.WriteLine(globalBunny); // โ
Works - class-level
// Console.WriteLine(localBunny); // โ Error - different method
}
}
`
Scope Visualization:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Class Scope (globalBunny) โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Method Scope (localBunny) โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ Block Scope (blockBunny) โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ Exercises
- Basic: Create variables for your name (string), age (int), and height in meters (double). Print them.
-
Constants: Define a
constfor the speed of light (299792458 m/s) and use it in a calculation. - Scope: Create a method that demonstrates all three scope levels with different variables.
๐ Data Types
Understanding Data Types
Every piece of data in C# has a type that determines:
- ๐ฆ How much memory it uses
- ๐ข What values it can hold
- โก What operations you can perform
C# has two main categories:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ C# Data Types โ
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ VALUE TYPES โ REFERENCE TYPES โ
โ (Stored in Stack) โ (Stored in Heap) โ
โโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โข int, long โ โข string โ
โ โข float, double โ โข arrays โ
โ โข decimal โ โข classes โ
โ โข bool โ โข interfaces โ
โ โข char โ โข delegates โ
โ โข struct โ โข object โ
โโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Value Types (Stored on Stack)
Value types store data directly in their memory location. When you copy a value type, you get a completely independent copy.
Numeric Types
`csharp
// INTEGER TYPES (whole numbers)
byte smallNumber = 255; // 0 to 255 (1 byte)
short shortNumber = 32767; // -32,768 to 32,767 (2 bytes)
int regularNumber = 2147483647; // Most common for integers (4 bytes)
long bigNumber = 9223372036854775807L; // Very large numbers (8 bytes)
// Note the 'L' suffix!
// FLOATING-POINT TYPES (decimals)
float price = 19.99f; // 7 digits precision (4 bytes)
// Note the 'f' suffix!
double distance = 3.14159265359; // 15-16 digits precision (8 bytes)
// Default for decimals
decimal money = 1000.50m; // 28-29 digits precision (16 bytes)
// Best for financial calculations!
// Note the 'm' suffix!
`
When to use which numeric type:
| Type | Use Case | Example |
|---|---|---|
int |
Most counting/indexing | Loop counters, IDs, quantities |
long |
Very large numbers | File sizes, timestamps |
double |
Scientific calculations | Physics, graphics, general math |
decimal |
Money/financial | Prices, currency, accounting |
float |
Memory-constrained | Game development, large arrays |
Boolean Type
Represents true or false only:
`csharp
bool isLoggedIn = true;
bool hasPermission = false;
bool isAdult = age >= 18; // Result of comparison
// Used in conditions
if (isLoggedIn && hasPermission)
{
Console.WriteLine("Access granted");
}
`
Character Type
Stores a single Unicode character:
`csharp
char letter = 'A'; // Single quotes for char!
char digit = '7';
char symbol = '$';
char emoji = '๐ฐ'; // Unicode supported
char newLine = '\n'; // Escape character
// Common escape characters:
// \n = new line
// \t = tab
// \ = backslash
// \" = double quote
`
Reference Types (Stored on Heap)
Reference types store a reference (pointer) to the data's location in memory. Multiple variables can reference the same object.
String Type
A sequence of characters (text):
`csharp
string greeting = "Hello, World!";
string name = "Lucy";
string empty = ""; // Empty string
string nothing = null; // No string at all
// String concatenation (combining strings)
string fullGreeting = greeting + " My name is " + name;
// String interpolation (preferred - cleaner syntax)
string message = $"Hello, {name}! You have {5} new messages.";
// Verbatim strings (ignore escape characters)
string path = @"C:\Users\Lucy\Documents"; // No need to escape \
// Multi-line strings (C# 11+)
string json = """
{
"name": "Lucy",
"age": 3
}
""";
`
Important String Methods:
`csharp
string text = " Hello, World! ";
text.Length; // 17 (includes spaces)
text.ToUpper(); // " HELLO, WORLD! "
text.ToLower(); // " hello, world! "
text.Trim(); // "Hello, World!" (removes whitespace)
text.Contains("World"); // true
text.StartsWith(" H"); // true
text.Replace("World", "C#"); // " Hello, C#! "
text.Split(','); // [" Hello", " World! "]
text.Substring(2, 5); // "Hello"
`
Object Type
The base type of ALL types in C#. Any value can be stored in an object:
`csharp
object anything = "I'm a string";
anything = 42; // Now I'm an int
anything = true; // Now I'm a bool
anything = new DateTime(); // Now I'm a DateTime
// You need to cast back to use type-specific features
object boxed = 100;
int unboxed = (int)boxed; // Explicit cast required
`
Value vs Reference Types - The Key Difference
`csharp
// VALUE TYPES - Independent copies
int a = 10;
int b = a; // b gets a COPY of a's value
b = 20; // Changing b doesn't affect a
Console.WriteLine(a); // Still 10!
Console.WriteLine(b); // 20
// REFERENCE TYPES - Same object, multiple references
int[] arr1 = { 1, 2, 3 };
int[] arr2 = arr1; // arr2 points to SAME array as arr1
arr2[0] = 99; // Modifying through arr2...
Console.WriteLine(arr1[0]); // ...changes arr1 too! Output: 99
`
Visual Representation:
VALUE TYPES: REFERENCE TYPES:
โโโโโโโ โโโโโโโ โโโโโโโ โโโโโโโโโโโโโโโ
โ a=10โ โ b=20โ โarr1 โโโโโถโ {99, 2, 3} โ
โโโโโโโ โโโโโโโ โโโโโโโ โโโโโโโโโโโโโโโ
Independent copies โฒ
โโโโโโโ โ
โarr2 โโโโโโโโโโโ
โโโโโโโ
Same object!
Nullable Types
By default, value types cannot be null. Use ? to make them nullable:
`csharp
// Regular value types - cannot be null
int age = 25;
// age = null; // โ Compile error!
// Nullable value types - CAN be null
int? nullableAge = null; // โ
This is allowed
nullableAge = 25; // Can also hold regular values
// Checking for null
if (nullableAge.HasValue)
{
Console.WriteLine(nullableAge.Value); // 25
}
// Null-coalescing operator (??) - provide default if null
int displayAge = nullableAge ?? 0; // If null, use 0
// Null-coalescing assignment (??=) - assign only if null
nullableAge ??= 18; // Only assigns 18 if nullableAge is null
// Null-conditional operator (?.) - safe navigation
string? name = null;
int? length = name?.Length; // Returns null instead of crashing
`
๐ Exercises
- Create variables for each numeric type and print their values.
- Demonstrate the difference between value and reference types using arrays.
- Use nullable types and null-coalescing operators to handle missing data.
โ Operators
What are Operators?
Operators are symbols that perform operations on values (operands). C# has several categories of operators.
Arithmetic Operators
Perform mathematical calculations:
`csharp
int a = 10;
int b = 3;
// Basic operations
Console.WriteLine(a + b); // Addition: 13
Console.WriteLine(a - b); // Subtraction: 7
Console.WriteLine(a * b); // Multiplication: 30
Console.WriteLine(a / b); // Division: 3 (integer division!)
Console.WriteLine(a % b); // Modulus: 1 (remainder)
// โ ๏ธ Integer division truncates decimals!
Console.WriteLine(10 / 3); // 3 (not 3.33!)
Console.WriteLine(10.0 / 3); // 3.333... (use double for decimals)
// Increment and Decrement
int x = 5;
Console.WriteLine(x++); // Post-increment: prints 5, then x becomes 6
Console.WriteLine(++x); // Pre-increment: x becomes 7, then prints 7
Console.WriteLine(x--); // Post-decrement: prints 7, then x becomes 6
Console.WriteLine(--x); // Pre-decrement: x becomes 5, then prints 5
`
Comparison Operators
Compare values and return bool (true/false):
`csharp
int age = 25;
int limit = 18;
Console.WriteLine(age == limit); // Equal to: false
Console.WriteLine(age != limit); // Not equal to: true
Console.WriteLine(age > limit); // Greater than: true
Console.WriteLine(age < limit); // Less than: false
Console.WriteLine(age >= 18); // Greater than or equal: true
Console.WriteLine(age <= 30); // Less than or equal: true
// Comparing strings
string a = "hello";
string b = "Hello";
Console.WriteLine(a == b); // false (case-sensitive)
Console.WriteLine(a.Equals(b, StringComparison.OrdinalIgnoreCase)); // true
`
Logical Operators
Combine boolean expressions:
`csharp
bool isAdult = true;
bool hasLicense = false;
bool hasInsurance = true;
// AND (&&) - Both must be true
Console.WriteLine(isAdult && hasLicense); // false
// OR (||) - At least one must be true
Console.WriteLine(hasLicense || hasInsurance); // true
// NOT (!) - Reverses the value
Console.WriteLine(!isAdult); // false
// Complex conditions
bool canDrive = isAdult && hasLicense && hasInsurance;
bool needsHelp = !hasLicense || !hasInsurance;
// Short-circuit evaluation
// && stops if first is false (no need to check second)
// || stops if first is true (no need to check second)
`
Assignment Operators
Assign and modify values:
`csharp
int x = 10; // Basic assignment
x += 5; // Add and assign: x = x + 5 โ 15
x -= 3; // Subtract and assign: x = x - 3 โ 12
x *= 2; // Multiply and assign: x = x * 2 โ 24
x /= 4; // Divide and assign: x = x / 4 โ 6
x %= 4; // Modulus and assign: x = x % 4 โ 2
// Also works with strings
string greeting = "Hello";
greeting += ", World!"; // "Hello, World!"
`
Ternary Operator
A shorthand for simple if-else:
`csharp
// Syntax: condition ? valueIfTrue : valueIfFalse
int age = 20;
string status = age >= 18 ? "Adult" : "Minor";
Console.WriteLine(status); // "Adult"
// Equivalent to:
string status2;
if (age >= 18)
status2 = "Adult";
else
status2 = "Minor";
// Can be nested (but avoid for readability)
string category = age < 13 ? "Child" : age < 20 ? "Teen" : "Adult";
`
Null-Related Operators
Handle null values safely:
`csharp
string? name = null;
// Null-coalescing (??) - provide default
string displayName = name ?? "Guest"; // "Guest"
// Null-coalescing assignment (??=)
name ??= "Default"; // Assigns only if name is null
// Null-conditional (?.) - safe member access
int? length = name?.Length; // null (doesn't crash!)
string? upper = name?.ToUpper();
// Null-forgiving (!) - tells compiler "I know this isn't null"
string definitelyNotNull = name!; // Use with caution!
`
๐ Type Casting
What is Type Casting?
Type casting (or type conversion) is changing a value from one data type to another.
Implicit Casting (Automatic)
Happens automatically when converting to a larger/compatible type (no data loss):
`csharp
// Smaller โ Larger (safe, no data loss)
int myInt = 100;
long myLong = myInt; // int โ long (automatic)
float myFloat = myLong; // long โ float (automatic)
double myDouble = myFloat; // float โ double (automatic)
// Conversion hierarchy (implicit):
// byte โ short โ int โ long โ float โ double
// โ
// decimal
`
Explicit Casting (Manual)
Required when converting to a smaller type (potential data loss):
`csharp
// Larger โ Smaller (may lose data!)
double myDouble = 9.78;
int myInt = (int)myDouble; // 9 (decimal part lost!)
long bigNumber = 1000L;
int smallerNumber = (int)bigNumber; // Works if value fits
// โ ๏ธ Overflow danger!
int tooBig = 300;
byte tooSmall = (byte)tooBig; // 44 (overflow - wraps around!)
`
Type Conversion Methods
For converting between incompatible types:
`csharp
// STRING โ NUMBER
string ageText = "25";
// Method 1: Parse (throws if invalid)
int age1 = int.Parse(ageText); // 25
double price1 = double.Parse("19.99"); // 19.99
// Method 2: Convert class (handles null)
int age2 = Convert.ToInt32(ageText); // 25
int fromNull = Convert.ToInt32(null); // 0 (doesn't throw!)
// Method 3: TryParse (safest - doesn't throw)
if (int.TryParse(ageText, out int result))
{
Console.WriteLine($"Parsed: {result}"); // 25
}
else
{
Console.WriteLine("Invalid number");
}
// NUMBER โ STRING
int number = 42;
string text1 = number.ToString(); // "42"
string text2 = Convert.ToString(number); // "42"
string text3 = $"{number}"; // "42" (interpolation)
// Formatting numbers as strings
double price = 1234.567;
Console.WriteLine(price.ToString("C")); // $1,234.57 (currency)
Console.WriteLine(price.ToString("F2")); // 1234.57 (2 decimals)
Console.WriteLine(price.ToString("N0")); // 1,235 (no decimals, with commas)
Console.WriteLine(price.ToString("P1")); // 123,456.7% (percentage)
`
๐ง Functions (Methods)
What is a Method?
A method (also called function) is a reusable block of code that performs a specific task. Methods help organize code and avoid repetition (DRY principle).
`csharp
// Method anatomy:
// [access modifier] [static?] [return type] MethodName([parameters])
// {
// // method body
// return value; // if return type isn't void
// }
public static int Add(int a, int b)
{
return a + b;
}
`
Method Declaration & Calling
`csharp
class Calculator
{
// Method with no parameters, no return value (void)
static void SayHello()
{
Console.WriteLine("Hello, World!");
}
// Method with parameters
static void Greet(string name)
{
Console.WriteLine($"Hello, {name}!");
}
// Method with return value
static int Add(int a, int b)
{
return a + b; // Must return an int
}
// Method with multiple parameters and return
static double CalculateArea(double width, double height)
{
double area = width * height;
return area;
}
static void Main()
{
// Calling methods
SayHello(); // Hello, World!
Greet("Lucy"); // Hello, Lucy!
int sum = Add(5, 3); // sum = 8
Console.WriteLine(sum);
double area = CalculateArea(4.5, 3.0); // area = 13.5
Console.WriteLine($"Area: {area}");
}
}
`
Parameters: Default, Named, and Params
`csharp
// DEFAULT PARAMETERS - Optional with fallback values
static void CreateUser(string name, int age = 18, string role = "User")
{
Console.WriteLine($"{name}, {age} years old, Role: {role}");
}
CreateUser("Alice"); // Alice, 18 years old, Role: User
CreateUser("Bob", 25); // Bob, 25 years old, Role: User
CreateUser("Carol", 30, "Admin"); // Carol, 30 years old, Role: Admin
// NAMED PARAMETERS - Specify by name (any order)
CreateUser(role: "Moderator", name: "Dave"); // Dave, 18 years old, Role: Moderator
// PARAMS - Variable number of arguments
static int Sum(params int[] numbers)
{
int total = 0;
foreach (int num in numbers)
{
total += num;
}
return total;
}
Console.WriteLine(Sum(1, 2)); // 3
Console.WriteLine(Sum(1, 2, 3, 4, 5)); // 15
Console.WriteLine(Sum()); // 0 (no arguments)
`
Out, Ref, and In Parameters
`csharp
// OUT - Method MUST assign a value (returns multiple values)
static void GetMinMax(int[] numbers, out int min, out int max)
{
min = numbers.Min();
max = numbers.Max();
}
int[] data = { 5, 2, 8, 1, 9 };
GetMinMax(data, out int minimum, out int maximum);
Console.WriteLine($"Min: {minimum}, Max: {maximum}"); // Min: 1, Max: 9
// REF - Pass by reference (can read AND modify)
static void Double(ref int number)
{
number *= 2; // Modifies the original variable!
}
int value = 10;
Double(ref value);
Console.WriteLine(value); // 20 (original was modified!)
// IN - Pass by reference but READ-ONLY (for large structs)
static void PrintPoint(in Point p)
{
Console.WriteLine($"X: {p.X}, Y: {p.Y}");
// p.X = 10; // โ Error: cannot modify 'in' parameter
}
`
Expression-Bodied Methods
Shorter syntax for simple methods:
`csharp
// Traditional method
static int Square(int x)
{
return x * x;
}
// Expression-bodied (arrow syntax) - same result
static int Square(int x) => x * x;
// More examples
static string GetFullName(string first, string last) => $"{first} {last}";
static bool IsAdult(int age) => age >= 18;
static void Log(string message) => Console.WriteLine($"[LOG] {message}");
`
๐ฆ Arrays and Collections
Arrays
An array is a fixed-size collection of elements of the same type:
`csharp
// Declaration and initialization
string[] bunnies = { "Lucy", "Tom", "Molly" }; // Shorthand
int[] numbers = new int[5]; // 5 zeros
double[] prices = new double[] { 9.99, 19.99, 29.99 }; // Explicit
// Accessing elements (0-indexed!)
Console.WriteLine(bunnies[0]); // "Lucy" (first element)
Console.WriteLine(bunnies[1]); // "Tom" (second element)
Console.WriteLine(bunnies[^1]); // "Molly" (last element - C# 8+)
// Modifying elements
bunnies[0] = "Peter"; // Replace "Lucy" with "Peter"
// Array properties
Console.WriteLine(bunnies.Length); // 3
// Iterating
for (int i = 0; i < bunnies.Length; i++)
{
Console.WriteLine($"Index {i}: {bunnies[i]}");
}
foreach (string bunny in bunnies)
{
Console.WriteLine(bunny);
}
`
Lists (Dynamic Arrays)
Lists can grow and shrink dynamically:
`csharp
using System.Collections.Generic;
// Creating lists
List bunnies = new List(); // Empty
List numbers = new List { 1, 2, 3, 4, 5 }; // With items
var names = new List { "Lucy", "Tom" }; // Using var
// Adding elements
bunnies.Add("Lucy"); // Add to end
bunnies.Add("Tom");
bunnies.Insert(0, "Peter"); // Insert at index 0
// Removing elements
bunnies.Remove("Tom"); // Remove by value (first occurrence)
bunnies.RemoveAt(0); // Remove by index
bunnies.Clear(); // Remove all
// Accessing elements
Console.WriteLine(names[0]); // "Lucy"
Console.WriteLine(names.Count); // 2
// Searching
bool hasLucy = names.Contains("Lucy"); // true
int index = names.IndexOf("Tom"); // 1
string? found = names.Find(n => n.StartsWith("L")); // "Lucy"
// Sorting
names.Sort(); // Alphabetical
names.Reverse(); // Reverse order
names.Sort((a, b) => b.CompareTo(a)); // Custom: descending
`
Dictionaries (Key-Value Pairs)
Store data as key-value pairs for fast lookup:
`csharp
// Creating dictionaries
Dictionary ages = new Dictionary();
var bunnyColors = new Dictionary
{
{ "Lucy", "White" },
{ "Tom", "Black" },
{ "Molly", "Brown" }
};
// Adding/updating
ages["Lucy"] = 3; // Add or update
ages.Add("Tom", 5); // Add only (throws if exists)
ages.TryAdd("Molly", 2); // Add only (returns false if exists)
// Accessing
string lucyColor = bunnyColors["Lucy"]; // "White"
// Safe access (avoid exceptions)
if (bunnyColors.TryGetValue("Tom", out string? color))
{
Console.WriteLine($"Tom is {color}");
}
// Checking existence
bool hasLucy = bunnyColors.ContainsKey("Lucy"); // true
bool hasGray = bunnyColors.ContainsValue("Gray"); // false
// Iterating
foreach (var pair in bunnyColors)
{
Console.WriteLine($"{pair.Key}: {pair.Value}");
}
// Or with deconstruction
foreach (var (name, bunnyColor) in bunnyColors)
{
Console.WriteLine($"{name} is {bunnyColor}");
}
`
โ Conditional Statements
If-Else Statements
Make decisions based on conditions:
`csharp
int score = 85;
// Simple if
if (score >= 60)
{
Console.WriteLine("Passed!");
}
// If-else
if (score >= 60)
{
Console.WriteLine("Passed!");
}
else
{
Console.WriteLine("Failed!");
}
// If-else if-else (multiple conditions)
if (score >= 90)
{
Console.WriteLine("Grade: A");
}
else if (score >= 80)
{
Console.WriteLine("Grade: B");
}
else if (score >= 70)
{
Console.WriteLine("Grade: C");
}
else if (score >= 60)
{
Console.WriteLine("Grade: D");
}
else
{
Console.WriteLine("Grade: F");
}
`
Switch Statement
Better than multiple if-else for checking one value against many cases:
`csharp
string day = "Monday";
switch (day)
{
case "Monday":
case "Tuesday":
case "Wednesday":
case "Thursday":
case "Friday":
Console.WriteLine("Weekday");
break;
case "Saturday":
case "Sunday":
Console.WriteLine("Weekend!");
break;
default:
Console.WriteLine("Invalid day");
break;
}
`
Switch Expression (C# 8+)
Modern, concise syntax that returns a value:
`csharp
string day = "Monday";
string dayType = day switch
{
"Monday" or "Tuesday" or "Wednesday" or "Thursday" or "Friday" => "Weekday",
"Saturday" or "Sunday" => "Weekend!",
_ => "Invalid day" // _ is the default/discard pattern
};
Console.WriteLine(dayType);
// With pattern matching
int score = 85;
string grade = score switch
{
>= 90 => "A",
>= 80 => "B",
>= 70 => "C",
>= 60 => "D",
_ => "F"
};
`
Ternary Operator
One-line conditional expression:
`csharp
int age = 20;
// condition ? trueValue : falseValue
string status = age >= 18 ? "Adult" : "Minor";
// Can be nested (but avoid for readability)
string ticket = age < 12 ? "Child" : age < 65 ? "Adult" : "Senior";
// Null-conditional pattern
string? name = null;
string display = name ?? "Guest"; // Use "Guest" if null
`
๐ Loops
For Loop
Best when you know how many iterations you need:
`csharp
// Basic for loop
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Iteration {i}"); // 0, 1, 2, 3, 4
}
// Counting backwards
for (int i = 10; i > 0; i--)
{
Console.WriteLine(i); // 10, 9, 8, ..., 1
}
// Stepping by 2
for (int i = 0; i <= 10; i += 2)
{
Console.WriteLine(i); // 0, 2, 4, 6, 8, 10
}
// Iterating array with index
string[] names = { "Lucy", "Tom", "Molly" };
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine($"{i}: {names[i]}");
}
`
Foreach Loop
Best for iterating through collections:
`csharp
string[] bunnies = { "Lucy", "Tom", "Molly" };
foreach (string bunny in bunnies)
{
Console.WriteLine($"{bunny} is ready for checkup!");
}
// Works with any collection
List numbers = new() { 1, 2, 3, 4, 5 };
foreach (int num in numbers)
{
Console.WriteLine(num * 2);
}
// With dictionaries
Dictionary ages = new() { ["Lucy"] = 3, ["Tom"] = 5 };
foreach (var (name, age) in ages)
{
Console.WriteLine($"{name} is {age}");
}
`
While Loop
Continues while a condition is true:
`csharp
int count = 0;
while (count < 5)
{
Console.WriteLine($"Count: {count}");
count++;
}
// Reading until valid input
string input = "";
while (string.IsNullOrEmpty(input))
{
Console.Write("Enter your name: ");
input = Console.ReadLine() ?? "";
}
`
Do-While Loop
Runs at least once, then checks the condition:
`csharp
int number;
do
{
Console.Write("Enter a positive number: ");
number = int.Parse(Console.ReadLine() ?? "0");
} while (number <= 0);
Console.WriteLine($"You entered: {number}");
`
Break and Continue
Control loop flow:
`csharp
// BREAK - Exit the loop immediately
for (int i = 0; i < 10; i++)
{
if (i == 5) break; // Stop at 5
Console.WriteLine(i); // 0, 1, 2, 3, 4
}
// CONTINUE - Skip to next iteration
for (int i = 0; i < 5; i++)
{
if (i == 2) continue; // Skip 2
Console.WriteLine(i); // 0, 1, 3, 4
}
`
โ ๏ธ Exception Handling
What are Exceptions?
Exceptions are errors that occur during program execution. Without handling, they crash your program!
Try-Catch-Finally
csharp
try
{
// Code that might throw an exception
int result = 10 / 0; // DivideByZeroException!
}
catch (DivideByZeroException ex)
{
// Handle specific exception
Console.WriteLine($"Cannot divide by zero: {ex.Message}");
}
catch (Exception ex)
{
// Handle any other exception
Console.WriteLine($"An error occurred: {ex.Message}");
}
finally
{
// ALWAYS runs (cleanup code)
Console.WriteLine("Cleanup complete");
}
Common Exception Types
| Exception | Cause |
|---|---|
NullReferenceException |
Accessing a null object |
IndexOutOfRangeException |
Array index out of bounds |
DivideByZeroException |
Division by zero |
FormatException |
Invalid format (e.g., parsing) |
ArgumentException |
Invalid argument passed |
InvalidOperationException |
Invalid operation for current state |
Throwing Exceptions
`csharp
static void SetAge(int age)
{
if (age < 0)
{
throw new ArgumentException("Age cannot be negative", nameof(age));
}
if (age > 150)
{
throw new ArgumentOutOfRangeException(nameof(age), "Age is unrealistic");
}
// ... rest of logic
}
// Custom exceptions
public class InsufficientFundsException : Exception
{
public decimal Balance { get; }
public decimal Attempted { get; }
public InsufficientFundsException(decimal balance, decimal attempted)
: base($"Insufficient funds. Balance: {balance:C}, Attempted: {attempted:C}")
{
Balance = balance;
Attempted = attempted;
}
}
`
๐๏ธ Classes and Objects
What is a Class?
A class is a blueprint for creating objects. It defines properties (data) and methods (behavior).
`csharp
public class Bunny
{
// Fields (private data)
private string name;
private int age;
// Properties (public access to data)
public string Name
{
get { return name; }
set { name = value; }
}
public int Age
{
get { return age; }
set { age = value >= 0 ? value : 0; } // Validation!
}
// Constructor (initializes new objects)
public Bunny(string name, int age)
{
this.name = name;
this.age = age;
}
// Methods (behavior)
public void Speak()
{
Console.WriteLine($"{Name} says: Squeak!");
}
// Static method (belongs to class, not instances)
public static void Info()
{
Console.WriteLine("Bunnies are cute pets!");
}
}
// Using the class
Bunny lucy = new Bunny("Lucy", 3);
lucy.Speak(); // Lucy says: Squeak!
Console.WriteLine(lucy.Name); // Lucy
Bunny.Info(); // Static method - called on class
`
Auto-Properties (Simplified)
`csharp
public class Bunny
{
// Auto-implemented properties (compiler creates backing field)
public string Name { get; set; }
public int Age { get; set; }
public string Color { get; init; } // Can only set during initialization
public bool IsAdult => Age >= 1; // Computed property
// Constructor
public Bunny(string name, int age, string color)
{
Name = name;
Age = age;
Color = color;
}
}
// Object initializer syntax
var bunny = new Bunny("Lucy", 3, "White");
// Or with object initializer
var bunny2 = new Bunny("Tom", 2, "Black") { Name = "Tommy" };
`
๐ Inheritance & Interfaces
Inheritance
Create new classes based on existing ones:
`csharp
// Base class
public class Animal
{
public string Name { get; set; }
public virtual void Speak() // 'virtual' allows overriding
{
Console.WriteLine("Some sound");
}
}
// Derived class
public class Bunny : Animal // Bunny inherits from Animal
{
public string Color { get; set; }
public override void Speak() // Override base implementation
{
Console.WriteLine($"{Name} says: Squeak!");
}
public void Hop() => Console.WriteLine($"{Name} is hopping!");
}
// Usage
Bunny bunny = new Bunny { Name = "Lucy", Color = "White" };
bunny.Speak(); // Lucy says: Squeak!
bunny.Hop(); // Lucy is hopping!
`
Interfaces
Define a contract that classes must implement:
`csharp
public interface IAnimal
{
string Name { get; set; }
void Speak();
void Move();
}
public class Bunny : IAnimal
{
public string Name { get; set; }
public void Speak() => Console.WriteLine($"{Name}: Squeak!");
public void Move() => Console.WriteLine($"{Name} hops!");
}
public class Dog : IAnimal
{
public string Name { get; set; }
public void Speak() => Console.WriteLine($"{Name}: Woof!");
public void Move() => Console.WriteLine($"{Name} runs!");
}
// Polymorphism - treat different types uniformly
IAnimal[] animals = { new Bunny { Name = "Lucy" }, new Dog { Name = "Max" } };
foreach (IAnimal animal in animals)
{
animal.Speak(); // Each uses its own implementation
}
`
๐ LINQ
LINQ (Language Integrated Query) provides powerful data querying:
`csharp
using System.Linq;
var bunnies = new List
{
new Bunny { Name = "Lucy", Age = 3, Color = "White" },
new Bunny { Name = "Tom", Age = 5, Color = "Black" },
new Bunny { Name = "Molly", Age = 2, Color = "White" }
};
// WHERE - Filter
var whiteBunnies = bunnies.Where(b => b.Color == "White");
// SELECT - Transform
var names = bunnies.Select(b => b.Name); // ["Lucy", "Tom", "Molly"]
// ORDERBY - Sort
var byAge = bunnies.OrderBy(b => b.Age);
// FIRST / FIRSTORDEFAULT - Get first match
var oldest = bunnies.OrderByDescending(b => b.Age).First();
var baby = bunnies.FirstOrDefault(b => b.Age < 1); // null if not found
// AGGREGATE FUNCTIONS
int totalAge = bunnies.Sum(b => b.Age); // 10
double avgAge = bunnies.Average(b => b.Age); // 3.33
int count = bunnies.Count(b => b.Age > 2); // 2
// ANY / ALL
bool hasOld = bunnies.Any(b => b.Age > 4); // true
bool allWhite = bunnies.All(b => b.Color == "White"); // false
`
โณ Async/Await
Handle asynchronous operations without blocking:
`csharp
using System.Net.Http;
// Async method declaration
public static async Task FetchDataAsync(string url)
{
using HttpClient client = new();
string result = await client.GetStringAsync(url);
return result;
}
// Calling async methods
public static async Task Main()
{
Console.WriteLine("Fetching data...");
string data = await FetchDataAsync("https://api.example.com/data");
Console.WriteLine($"Received: {data}");
}
// Parallel async operations
public static async Task FetchMultipleAsync()
{
var task1 = FetchDataAsync("https://api.example.com/users");
var task2 = FetchDataAsync("https://api.example.com/posts");
// Wait for all to complete
string[] results = await Task.WhenAll(task1, task2);
}
`
๐งฎ Calculator Exercise
`csharp
public class Calculator
{
public double Add(double x, double y) => x + y;
public double Subtract(double x, double y) => x - y;
public double Multiply(double x, double y) => x * y;
public double Divide(double x, double y) =>
y != 0 ? x / y : throw new DivideByZeroException();
public double Power(double x, double y) => Math.Pow(x, y);
public double Square(double x) => x * x;
public double SquareRoot(double x) => Math.Sqrt(x);
}
// Usage
var calc = new Calculator();
Console.WriteLine(calc.Add(5, 3)); // 8
Console.WriteLine(calc.Multiply(4, 7)); // 28
Console.WriteLine(calc.Power(2, 8)); // 256
`
๐ Resources
๐ค Contributing
- Fork this repository
- Create a new branch
- Make your changes
- Submit a pull request
โญ Show Your Support
Give a โญ if this helped you!
Made with โค๏ธ for C# learners
Top comments (0)