Getting to Know C# Programming Language
What is C#?
C# (pronounced "C-Sharp") is a modern, object-oriented programming language developed by Microsoft. It's designed to be simple, powerful, and type-safe, making it ideal for building various types of applications on the .NET platform.
C# Language Features
Modern Language Design
// Modern C# syntax examples
var greeting = "Hello, World!";
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var person = new { Name = "John", Age = 30 };
// Null-conditional operators
string result = person?.Name?.ToUpper();
// String interpolation
Console.WriteLine($"Hello, {person.Name}!");
C# Language Evolution
timeline
title C# Version History
2000 : C# 1.0
: Basic OOP Features
2005 : C# 2.0
: Generics, Nullable Types
2007 : C# 3.0
: LINQ, Lambda Expressions
2010 : C# 4.0
: Dynamic Typing, Optional Parameters
2012 : C# 5.0
: Async/Await
2015 : C# 6.0
: String Interpolation, Null-conditional
2017 : C# 7.0
: Tuples, Pattern Matching
2019 : C# 8.0
: Nullable Reference Types
2020 : C# 9.0
: Records, Init-only Properties
2021 : C# 10.0
: Global Using, File-scoped Namespaces
2022 : C# 11.0
: Raw String Literals, Pattern Matching
2023 : C# 12.0
: Primary Constructors, Collection Expressions
Basic Syntax and Structure
Hello World Program
// Traditional approach
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
}
// Modern approach (C# 9.0+)
using System;
Console.WriteLine("Hello, World!");
Variables and Data Types
// Value types
int age = 25;
double price = 99.99;
bool isActive = true;
char initial = 'A';
decimal salary = 50000.00m;
// Reference types
string name = "John Doe";
object data = new { Id = 1, Name = "Product" };
// Nullable types
int? optionalNumber = null;
string? optionalText = null;
// Implicitly typed variables
var number = 42; // int
var text = "Hello"; // string
var list = new List<int>(); // List<int>
Constants and Readonly
// Constants (compile-time)
const int MAX_SIZE = 100;
const string COMPANY_NAME = "TechCorp";
// Readonly (runtime)
readonly DateTime createdAt = DateTime.Now;
public class Configuration
{
public static readonly string ConnectionString =
Environment.GetEnvironmentVariable("DB_CONNECTION");
}
Object-Oriented Programming
Classes and Objects
// Class definition
public class Person
{
// Fields
private string _firstName;
private string _lastName;
// Properties
public string FirstName
{
get => _firstName;
set => _firstName = value?.Trim();
}
public string LastName
{
get => _lastName;
set => _lastName = value?.Trim();
}
// Auto-implemented property
public int Age { get; set; }
// Read-only property
public string FullName => $"{FirstName} {LastName}";
// Constructor
public Person(string firstName, string lastName, int age)
{
FirstName = firstName;
LastName = lastName;
Age = age;
}
// Methods
public void Introduce()
{
Console.WriteLine($"Hi, I'm {FullName} and I'm {Age} years old.");
}
public bool IsAdult() => Age >= 18;
}
// Using the class
var person = new Person("John", "Doe", 30);
person.Introduce();
Console.WriteLine($"Is adult: {person.IsAdult()}");
Inheritance
// Base class
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public virtual void MakeSound()
{
Console.WriteLine("The animal makes a sound");
}
public virtual void Move()
{
Console.WriteLine("The animal moves");
}
}
// Derived class
public class Dog : Animal
{
public string Breed { get; set; }
public override void MakeSound()
{
Console.WriteLine($"{Name} barks: Woof! Woof!");
}
public override void Move()
{
Console.WriteLine($"{Name} runs around");
}
public void Fetch()
{
Console.WriteLine($"{Name} fetches the ball");
}
}
// Usage
var dog = new Dog
{
Name = "Buddy",
Age = 3,
Breed = "Golden Retriever"
};
dog.MakeSound(); // Buddy barks: Woof! Woof!
dog.Move(); // Buddy runs around
dog.Fetch(); // Buddy fetches the ball
Interfaces
// Interface definition
public interface IShape
{
double Area { get; }
double Perimeter { get; }
void Draw();
}
// Interface implementation
public class Rectangle : IShape
{
public double Width { get; set; }
public double Height { get; set; }
public double Area => Width * Height;
public double Perimeter => 2 * (Width + Height);
public void Draw()
{
Console.WriteLine($"Drawing rectangle: {Width}x{Height}");
}
}
public class Circle : IShape
{
public double Radius { get; set; }
public double Area => Math.PI * Radius * Radius;
public double Perimeter => 2 * Math.PI * Radius;
public void Draw()
{
Console.WriteLine($"Drawing circle with radius: {Radius}");
}
}
// Using interfaces
List<IShape> shapes = new List<IShape>
{
new Rectangle { Width = 10, Height = 5 },
new Circle { Radius = 3 }
};
foreach (IShape shape in shapes)
{
shape.Draw();
Console.WriteLine($"Area: {shape.Area:F2}");
}
Collections and Generics
Common Collections
// Arrays
int[] numbers = { 1, 2, 3, 4, 5 };
string[] names = new string[3] { "John", "Jane", "Bob" };
// Lists
List<string> fruits = new List<string> { "Apple", "Banana", "Orange" };
fruits.Add("Grape");
fruits.Remove("Banana");
// Dictionaries
Dictionary<string, int> ages = new Dictionary<string, int>
{
["John"] = 30,
["Jane"] = 25,
["Bob"] = 35
};
// HashSet (unique values)
HashSet<string> uniqueNames = new HashSet<string> { "John", "Jane", "John" };
// uniqueNames contains only "John" and "Jane"
// Queue (FIFO)
Queue<string> taskQueue = new Queue<string>();
taskQueue.Enqueue("Task 1");
taskQueue.Enqueue("Task 2");
string nextTask = taskQueue.Dequeue(); // "Task 1"
// Stack (LIFO)
Stack<string> history = new Stack<string>();
history.Push("Page 1");
history.Push("Page 2");
string currentPage = history.Pop(); // "Page 2"
LINQ (Language Integrated Query)
List<Person> people = new List<Person>
{
new Person("John", "Doe", 30),
new Person("Jane", "Smith", 25),
new Person("Bob", "Johnson", 35),
new Person("Alice", "Brown", 28)
};
// LINQ query syntax
var adults = from person in people
where person.Age >= 30
orderby person.Age
select person;
// LINQ method syntax
var youngAdults = people
.Where(p => p.Age >= 25 && p.Age < 30)
.OrderBy(p => p.LastName)
.Select(p => new { p.FullName, p.Age })
.ToList();
// Common LINQ operations
var averageAge = people.Average(p => p.Age);
var oldestPerson = people.OrderByDescending(p => p.Age).First();
var namesList = people.Select(p => p.FullName).ToList();
var groupsByAge = people.GroupBy(p => p.Age >= 30 ? "Adult" : "Young");
Exception Handling
public class FileProcessor
{
public string ReadFile(string filePath)
{
try
{
// Attempt to read file
return File.ReadAllText(filePath);
}
catch (FileNotFoundException ex)
{
Console.WriteLine($"File not found: {ex.Message}");
throw; // Re-throw to let caller handle
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"Access denied: {ex.Message}");
return string.Empty;
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex.Message}");
throw new InvalidOperationException("Failed to read file", ex);
}
finally
{
// Cleanup code (always executes)
Console.WriteLine("File operation completed");
}
}
}
// Custom exception
public class InvalidAgeException : Exception
{
public InvalidAgeException(int age)
: base($"Invalid age: {age}. Age must be between 0 and 150.")
{
Age = age;
}
public int Age { get; }
}
// Using custom exception
public void SetAge(int age)
{
if (age < 0 || age > 150)
throw new InvalidAgeException(age);
Age = age;
}
Async Programming
public class DataService
{
private readonly HttpClient _httpClient = new HttpClient();
// Async method
public async Task<string> GetDataAsync(string url)
{
try
{
HttpResponseMessage response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();
return content;
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Request failed: {ex.Message}");
throw;
}
}
// Async method with multiple operations
public async Task<List<string>> GetMultipleDataAsync(List<string> urls)
{
List<Task<string>> tasks = urls.Select(GetDataAsync).ToList();
string[] results = await Task.WhenAll(tasks);
return results.ToList();
}
}
// Using async methods
public async Task ProcessDataAsync()
{
var service = new DataService();
// Sequential execution
string data1 = await service.GetDataAsync("https://api.example.com/data1");
string data2 = await service.GetDataAsync("https://api.example.com/data2");
// Parallel execution
List<string> urls = new List<string>
{
"https://api.example.com/data1",
"https://api.example.com/data2",
"https://api.example.com/data3"
};
List<string> results = await service.GetMultipleDataAsync(urls);
}
Modern C# Features
Records (C# 9.0+)
// Record definition
public record Person(string FirstName, string LastName, int Age)
{
public string FullName => $"{FirstName} {LastName}";
}
// Usage
var person1 = new Person("John", "Doe", 30);
var person2 = person1 with { Age = 31 }; // Create copy with modified property
// Value equality
Console.WriteLine(person1 == person2); // False
Console.WriteLine(person1.FirstName == person2.FirstName); // True
Pattern Matching
public string DescribeObject(object obj)
{
return obj switch
{
int n when n > 0 => $"Positive number: {n}",
int n when n < 0 => $"Negative number: {n}",
int => "Zero",
string s when s.Length > 10 => $"Long string: {s[..10]}...",
string s => $"String: {s}",
List<int> list => $"List with {list.Count} items",
null => "Null value",
_ => "Unknown type"
};
}
// Using pattern matching
Console.WriteLine(DescribeObject(42)); // Positive number: 42
Console.WriteLine(DescribeObject("Hello")); // String: Hello
Console.WriteLine(DescribeObject(null)); // Null value
Nullable Reference Types (C# 8.0+)
#nullable enable
public class UserService
{
// Non-nullable reference type
public string GetUserName(int userId)
{
// Must return non-null string
return GetUserFromDatabase(userId)?.Name ?? "Unknown";
}
// Nullable reference type
public string? FindUserEmail(int userId)
{
// Can return null
return GetUserFromDatabase(userId)?.Email;
}
private User? GetUserFromDatabase(int userId)
{
// Implementation details...
return null; // Compiler knows this can be null
}
}
public class User
{
public string Name { get; set; } = string.Empty; // Must be initialized
public string? Email { get; set; } // Can be null
}
C# Programming Concepts Flow
graph TD
A[Basic Syntax] --> B[Variables & Types]
B --> C[Control Structures]
C --> D[Methods & Functions]
D --> E[Object-Oriented Programming]
E --> F[Classes & Objects]
E --> G[Inheritance]
E --> H[Interfaces]
E --> I[Polymorphism]
F --> J[Collections & Generics]
G --> J
H --> J
I --> J
J --> K[Exception Handling]
K --> L[Async Programming]
L --> M[Advanced Features]
M --> N[LINQ]
M --> O[Pattern Matching]
M --> P[Records]
M --> Q[Nullable Types]
Best Practices
Naming Conventions
// Classes, Methods, Properties - PascalCase
public class UserService
{
public string GetUserName() { ... }
public int UserId { get; set; }
}
// Fields, Variables, Parameters - camelCase
private string _userName;
public void ProcessUser(string firstName) { ... }
// Constants - PascalCase
public const int MaxRetryCount = 3;
// Interfaces - Start with 'I'
public interface IUserRepository { ... }
Code Organization
// Organize using statements
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Logging;
// Namespace matches folder structure
namespace MyApp.Services.User
{
// Class summary documentation
/// <summary>
/// Provides user-related operations and data access
/// </summary>
public class UserService
{
// Dependencies injection
private readonly ILogger<UserService> _logger;
private readonly IUserRepository _userRepository;
public UserService(ILogger<UserService> logger, IUserRepository userRepository)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_userRepository = userRepository ?? throw new ArgumentNullException(nameof(userRepository));
}
}
}
Common Patterns
Repository Pattern
public interface IUserRepository
{
Task<User?> GetByIdAsync(int id);
Task<List<User>> GetAllAsync();
Task<User> CreateAsync(User user);
Task UpdateAsync(User user);
Task DeleteAsync(int id);
}
public class UserRepository : IUserRepository
{
private readonly DbContext _context;
public UserRepository(DbContext context)
{
_context = context;
}
public async Task<User?> GetByIdAsync(int id)
{
return await _context.Users.FindAsync(id);
}
// Other implementations...
}
Dependency Injection
// Service registration
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IUserService, UserService>();
}
// Service usage
public class UserController : ControllerBase
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
}
Learning Path
Beginner Level
- Basic Syntax: Variables, data types, operators
- Control Flow: if/else, loops, switch
- Methods: Parameters, return values, overloading
- Classes: Properties, constructors, methods
Intermediate Level
- OOP Concepts: Inheritance, polymorphism, interfaces
- Collections: Lists, dictionaries, LINQ
- Exception Handling: try/catch/finally, custom exceptions
- File I/O: Reading/writing files, streams
Advanced Level
- Async Programming: async/await, Tasks, parallel processing
- Generics: Generic classes, constraints, variance
- Delegates & Events: Event handling, functional programming
- Reflection: Runtime type inspection, dynamic loading
Next Steps
After mastering C# basics:
- Understand .NET project structure
- Learn .NET CLI commands
- Explore NuGet package management
- Build your first .NET project
Summary
C# is a powerful, modern programming language that offers:
Feature | Benefit |
---|---|
Strong Typing | Compile-time error detection |
Object-Oriented | Code reusability and maintainability |
Memory Management | Automatic garbage collection |
Rich Libraries | Extensive Base Class Library |
Cross-Platform | Runs on multiple operating systems |
Modern Syntax | Expressive and readable code |
C# combines the power of C++ with the simplicity of Visual Basic, making it an excellent choice for both beginners and experienced developers building modern applications.