DEV Community

Cover image for CSharp-Basics
FredAbod
FredAbod

Posted on

CSharp-Basics

๐Ÿ’ป 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

  1. Fork and clone this repository
  2. Open the folder in VS Code or Visual Studio
  3. Open the terminal (Ctrl + ` in VS Code)
  4. Run the examples: bash dotnet run
  5. Edit Program.cs to uncomment different example methods
  6. 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 (like import in JS/Python)
  • namespace - Groups related classes together (prevents naming conflicts)
  • class - A blueprint/container for code and data
  • static void Main() - The entry point; static means no object needed, void means 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
}
Enter fullscreen mode Exit fullscreen mode

}
`

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
}
Enter fullscreen mode Exit fullscreen mode

}
`

Scope Visualization:


โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Class Scope (globalBunny) โ”‚
โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
โ”‚ โ”‚ Method Scope (localBunny) โ”‚ โ”‚
โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚
โ”‚ โ”‚ โ”‚ Block Scope (blockBunny) โ”‚ โ”‚ โ”‚
โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚
โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ“ Exercises

  1. Basic: Create variables for your name (string), age (int), and height in meters (double). Print them.
  2. Constants: Define a const for the speed of light (299792458 m/s) and use it in a calculation.
  3. 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

  1. Create variables for each numeric type and print their values.
  2. Demonstrate the difference between value and reference types using arrays.
  3. 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}");
}
Enter fullscreen mode Exit fullscreen mode

}
`

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;
}
Enter fullscreen mode Exit fullscreen mode

}
`


๐Ÿ—๏ธ 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!");
}
Enter fullscreen mode Exit fullscreen mode

}

// 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;
}
Enter fullscreen mode Exit fullscreen mode

}

// 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");
}
Enter fullscreen mode Exit fullscreen mode

}

// 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!");
Enter fullscreen mode Exit fullscreen mode

}

// 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}");
Enter fullscreen mode Exit fullscreen mode

}

// 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);
Enter fullscreen mode Exit fullscreen mode

}
`


๐Ÿงฎ 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

  1. Fork this repository
  2. Create a new branch
  3. Make your changes
  4. Submit a pull request

โญ Show Your Support

Give a โญ if this helped you!


Made with โค๏ธ for C# learners

Top comments (0)