Table of Contents
- Setting Up Your Environment
- Basic C# Syntax
- Intermediate C# Concepts
- Advanced C# Syntax
- Conclusion
- References
Setting Up Your Environment
Before diving into syntax, you’ll need to set up your development environment. Here’s what you need:
1. .NET SDK
C# runs on the .NET framework. Download the .NET SDK (choose the latest LTS version for stability). This includes the C# compiler (csc) and tools for building apps.
2. Code Editor/IDE
- Visual Studio: The most popular IDE for C# (free Community edition available). It includes debugging tools, IntelliSense, and project templates.
- Visual Studio Code: A lightweight code editor with C# extensions (install the C# extension for syntax highlighting and debugging).
- JetBrains Rider: A cross-platform IDE for .NET development (paid, but offers a free trial).
Basic C# Syntax
Structure of a C# Program
A basic C# program has a predictable structure. Let’s break down a “Hello World” example:
// Program.cs (top-level statement, C# 9.0+)
Console.WriteLine("Hello, World!");
Wait—where’s the class and Main method? In C# 9.0+, you can use top-level statements to simplify small programs, but under the hood, the compiler generates a class with a Main method. For clarity, here’s the explicit version (pre-C# 9.0):
using System; // Import namespace
namespace HelloWorldApp // Namespace: groups related code
{
class Program // Class: blueprint for objects
{
static void Main(string[] args) // Entry point of the program
{
Console.WriteLine("Hello, World!"); // Method call
}
}
}
Key Components:
usingDirective: Imports namespaces (e.g.,SystemforConsole).- Namespace: A container for classes (avoids naming conflicts).
- Class: A blueprint for creating objects (all C# code lives in classes).
MainMethod: The entry point of the program (runs first). Markedstaticbecause it belongs to the class, not an instance.
Variables and Data Types
Variables store data. In C#, you must declare a variable’s type before using it (statically typed).
Value Types vs. Reference Types
- Value Types: Store data directly in memory (e.g.,
int,bool,double). - Reference Types: Store a reference (memory address) to data (e.g.,
string,object, arrays).
Common Data Types
| Category | Types | Description | Example |
|---|---|---|---|
| Numeric | int, long, float | Integers and floating-point numbers | int age = 25; double pi = 3.14159; |
| Boolean | bool | True/false values | bool isActive = true; |
| Character | char | Single Unicode character | char grade = 'A'; |
| String | string | Sequence of characters (reference type) | string name = "Alice"; |
| Object | object | Base type for all C# types | object data = 42; (boxing) |
Variable Declaration
// Declaration + initialization
int score = 95;
string message = "Welcome!";
bool isStudent = true;
// Declaration first, initialization later
double temperature;
temperature = 23.5;
// Implicit typing (var: compiler infers type)
var count = 100; // var = int
var greeting = "Hello"; // var = string
Note: Use
varonly when the type is obvious (e.g.,var list = new List<int>();). Avoidvarfor primitive types likeintorstringfor readability.
Operators
Operators perform actions on variables and values.
1. Arithmetic Operators
int a = 10, b = 3;
Console.WriteLine(a + b); // 13 (addition)
Console.WriteLine(a - b); // 7 (subtraction)
Console.WriteLine(a * b); // 30 (multiplication)
Console.WriteLine(a / b); // 3 (integer division)
Console.WriteLine(a % b); // 1 (modulus/remainder)
2. Assignment Operators
int x = 5;
x += 3; // x = x + 3 → 8
x *= 2; // x = x * 2 → 16
3. Comparison Operators
int p = 5, q = 10;
Console.WriteLine(p == q); // false (equal)
Console.WriteLine(p != q); // true (not equal)
Console.WriteLine(p > q); // false (greater than)
4. Logical Operators
bool isSunny = true;
bool isWarm = false;
Console.WriteLine(isSunny && isWarm); // false (AND)
Console.WriteLine(isSunny || isWarm); // true (OR)
Console.WriteLine(!isWarm); // true (NOT)
Control Flow Statements
Control flow determines the order in which code executes.
1. if-else Statement
int age = 17;
if (age >= 18)
{
Console.WriteLine("Adult");
}
else if (age >= 13)
{
Console.WriteLine("Teenager");
}
else
{
Console.WriteLine("Child");
}
// Output: Teenager
2. switch Statement (C# 8.0+)
string day = "Wednesday";
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;
}
// Output: Weekday
3. Loops
-
forLoop: Iterate a fixed number of times.for (int i = 0; i < 5; i++) { Console.WriteLine(i); // 0, 1, 2, 3, 4 } -
foreachLoop: Iterate over collections/arrays.string[] fruits = { "Apple", "Banana", "Cherry" }; foreach (string fruit in fruits) { Console.WriteLine(fruit); // Apple, Banana, Cherry } -
whileLoop: Iterate while a condition is true.int count = 0; while (count < 3) { Console.WriteLine("Count: " + count); // 0, 1, 2 count++; } -
do-whileLoop: Executes once, then loops while a condition is true.int num = 5; do { Console.WriteLine(num); // 5 (executes once even if condition is false) num--; } while (num > 5);
Intermediate C# Concepts
Methods
A method is a reusable block of code that performs a task. It can take inputs (parameters) and return an output.
Method Declaration
// Access modifier | Return type | Name | Parameters
public static int Add(int a, int b)
{
return a + b; // Return result
}
// Call the method
int sum = Add(3, 5);
Console.WriteLine(sum); // 8
Key Components:
- Access Modifier:
public,private,protected, orinternal(controls visibility). - Return Type: The type of value returned (use
voidfor no return value). - Parameters: Inputs (optional; specify type and name).
Method Overloading
Define multiple methods with the same name but different parameters (different types or count):
public static int Multiply(int a, int b) => a * b;
public static double Multiply(double a, double b) => a * b;
// Calls
Console.WriteLine(Multiply(2, 3)); // 6 (int version)
Console.WriteLine(Multiply(2.5, 4.0)); // 10.0 (double version)
Arrays and Collections
Arrays store fixed-size collections of the same type. Collections (e.g., List<T>, Dictionary<TKey, TValue>) are dynamic and more flexible.
Arrays
// Declare and initialize an array
int[] numbers = { 1, 2, 3, 4, 5 };
// Access elements (0-based index)
Console.WriteLine(numbers[2]); // 3
// Modify elements
numbers[0] = 10;
// Array length
Console.WriteLine(numbers.Length); // 5
List<T> (Dynamic Array)
using System.Collections.Generic; // Required for List<T>
List<string> colors = new List<string>();
colors.Add("Red");
colors.Add("Blue");
colors.Add("Green");
Console.WriteLine(colors[1]); // Blue
Console.WriteLine(colors.Count); // 3 (dynamic size)
foreach (string color in colors)
{
Console.WriteLine(color); // Red, Blue, Green
}
Dictionary<TKey, TValue> (Key-Value Pairs)
Dictionary<string, int> studentGrades = new Dictionary<string, int>();
studentGrades.Add("Alice", 90);
studentGrades.Add("Bob", 85);
Console.WriteLine(studentGrades["Alice"]); // 90
foreach (var pair in studentGrades)
{
Console.WriteLine($"{pair.Key}: {pair.Value}"); // Alice: 90, Bob: 85
}
Strings
Strings are immutable (cannot be changed after creation). Use methods like Substring, Split, or ToUpper to manipulate them.
string text = "Hello, C#!";
// Length
Console.WriteLine(text.Length); // 9
// Substring (start index, length)
Console.WriteLine(text.Substring(7, 2)); // C#
// Split into array
string[] words = text.Split(','); // ["Hello", " C#!"]
// String interpolation (C# 6.0+)
string name = "Alice";
int age = 30;
string info = $"Name: {name}, Age: {age}"; // "Name: Alice, Age: 30"
Object-Oriented Programming (OOP) Basics
OOP organizes code into objects with properties (data) and methods (behavior).
Classes and Objects
A class is a blueprint; an object is an instance of a class.
// Class definition
public class Person
{
// Properties (data)
public string Name { get; set; } // Auto-implemented property
public int Age { get; set; }
// Constructor (initializes objects)
public Person(string name, int age)
{
Name = name;
Age = age;
}
// Method (behavior)
public void Greet()
{
Console.WriteLine($"Hello, my name is {Name} and I'm {Age} years old.");
}
}
// Create an object (instance)
Person alice = new Person("Alice", 30);
alice.Greet(); // Output: Hello, my name is Alice and I'm 30 years old.
Encapsulation
Use access modifiers to restrict access to class members:
public: Accessible everywhere.private: Accessible only within the class.protected: Accessible within the class and derived classes.
public class BankAccount
{
private decimal balance; // Private: only accessible via methods
public void Deposit(decimal amount)
{
if (amount > 0) balance += amount;
}
public decimal GetBalance()
{
return balance;
}
}
Inheritance
A derived class inherits from a base class to reuse code.
public class Animal // Base class
{
public void Eat()
{
Console.WriteLine("Eating...");
}
}
public class Dog : Animal // Derived class (inherits from Animal)
{
public void Bark()
{
Console.WriteLine("Woof!");
}
}
// Usage
Dog dog = new Dog();
dog.Eat(); // Inherited from Animal
dog.Bark(); // Defined in Dog
Advanced C# Syntax
Generics
Generics allow you to create reusable code that works with multiple types (without sacrificing type safety).
Generic Method Example
public static T Max<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b) > 0 ? a : b;
}
// Use with int, string, etc.
Console.WriteLine(Max(5, 10)); // 10 (int)
Console.WriteLine(Max("Apple", "Banana")); // Banana (string)
Generic Class Example
public class Box<T>
{
private T item;
public void SetItem(T item)
{
this.item = item;
}
public T GetItem()
{
return item;
}
}
// Usage
Box<int> intBox = new Box<int>();
intBox.SetItem(42);
Console.WriteLine(intBox.GetItem()); // 42
Box<string> stringBox = new Box<string>();
stringBox.SetItem("Hello");
Console.WriteLine(stringBox.GetItem()); // Hello
LINQ (Language Integrated Query)
LINQ simplifies querying collections (e.g., List<T>, arrays) using SQL-like syntax.
Example: Query a List of Objects
using System.Linq; // Required for LINQ
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
}
List<Product> products = new List<Product>
{
new Product { Name = "Laptop", Price = 999.99m },
new Product { Name = "Mouse", Price = 25.50m },
new Product { Name = "Keyboard", Price = 49.99m }
};
// LINQ Query Syntax
var cheapProducts = from p in products
where p.Price < 50
select p.Name;
// LINQ Method Syntax (more common)
var cheapProducts2 = products.Where(p => p.Price < 50).Select(p => p.Name);
foreach (var name in cheapProducts)
{
Console.WriteLine(name); // Mouse, Keyboard
}
Asynchronous Programming (Async/Await)
Async/await allows non-blocking code execution, critical for I/O-bound tasks (e.g., API calls, file reading).
using System.Threading.Tasks;
// Async method (returns Task or Task<T>)
public static async Task<string> FetchDataAsync()
{
// Simulate API call (non-blocking)
await Task.Delay(2000); // Wait 2 seconds without blocking
return "Data fetched!";
}
// Call async method
public static async Task Main()
{
Console.WriteLine("Fetching data...");
string result = await FetchDataAsync();
Console.WriteLine(result); // Output after 2 seconds: "Data fetched!"
}
Exception Handling
Exceptions are errors that occur during runtime. Use try-catch-finally to handle them gracefully.
try
{
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers[5]); // IndexOutOfRangeException
}
catch (IndexOutOfRangeException ex)
{
Console.WriteLine($"Error: {ex.Message}"); // Handle specific exception
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex.Message}"); // Catch-all (use sparingly)
}
finally
{
Console.WriteLine("This runs always (e.g., clean up resources)");
}
Custom Exceptions
Define your own exceptions for application-specific errors:
public class InsufficientFundsException : Exception
{
public InsufficientFundsException(string message) : base(message) { }
}
// Throw custom exception
if (balance < amount)
{
throw new InsufficientFundsException("Not enough money!");
}
Delegates and Events
Delegates
A delegate is a type-safe function pointer (points to a method with a specific signature).
// Define delegate type
public delegate int Calculator(int a, int b);
// Methods matching the delegate signature
public static int Add(int a, int b) => a + b;
public static int Subtract(int a, int b) => a - b;
// Use delegate
Calculator calc = Add;
Console.WriteLine(calc(5, 3)); // 8
calc = Subtract;
Console.WriteLine(calc(5, 3)); // 2
Events
Events are based on delegates and enable the observer pattern (e.g., button clicks).
public class Button
{
// Define event (uses EventHandler delegate)
public event EventHandler Clicked;
public void OnClick()
{
// Raise event if handlers are attached
Clicked?.Invoke(this, EventArgs.Empty);
}
}
// Subscribe to the event
Button button = new Button();
button.Clicked += (sender, e) => Console.WriteLine("Button clicked!");
// Trigger event
button.OnClick(); // Output: "Button clicked!"
Conclusion
C# syntax is the foundation of writing robust, maintainable code. From variables and control flow to advanced concepts like generics and async/await, each topic builds on the last. The key to mastery is practice: experiment with examples, build small projects, and refer to documentation when stuck.
Remember, syntax is just the start—C#’s true power lies in its ecosystem (ASP.NET, Unity, Azure) and object-oriented principles. Keep coding, and happy learning!