Skip to main content
C#

The Ultimate Cheat Sheet for C#

Looking to improve your C# programming skills? Look no further than this C# ultimate cheat sheet! Covering everything from the basics to advanced features, with real-world code examples. Learn object-oriented programming, collections, exception handling, file I/O, LINQ, multithreading, and more...

Christian Schou

Are you in the process of learning to write C# code or are you just looking for a piece of code to help you out? No matter if you are a novice or an expert, we often forget how some specific function has to be written.

C# is a modern, object-oriented programming language developed by Microsoft. It is widely used for developing Windows desktop applications, web applications, and games. C# is known for its simplicity, type safety, and scalability, making it an ideal choice for both beginner and advanced programmers.

As with any programming language, C# has its own syntax and rules that need to be understood to write effective code. While there are many resources available for learning C#, having a comprehensive cheat sheet can be incredibly helpful for quickly referencing key concepts, syntax, and best practices.

In this ultimate cheat sheet for C#, I'll cover everything you need to know to start writing C# code like a pro. From the basics of data types, variables, and control flow statements, to more advanced topics like object-oriented programming, multithreading, and LINQ, this cheatsheet has got you covered.

Whether you're a beginner looking to learn the basics of C#, or an experienced programmer looking for a quick reference guide, this cheat sheet will help you write better, more efficient code in C#. So let's get started! Happy coding 👨‍💻

🤓
If you got any suggestions for this C# Cheatsheet, please let me know in the comments below or by sending me a message. I will continuously update this post with extra snippets and help for C#.

Introduction

Writing a simple "Hello World" program using basic techniques

What is C# - In a nutshell?

C# is a simple, type-safe, general-purpose, object-oriented programming language created (in the early 2000s) and maintained by Microsoft. The project is led by a Danish guy named Anders Hejlsberg (yes, I'm a little proud to be a Dane right now).

C# is an object-oriented language, which means that it is based on the concept of classes and objects. It also features automatic memory management through the use of a garbage collector, which helps to simplify the development process and reduce the risk of memory leaks.

Why a cheat sheet for C# is useful

C# is a powerful and versatile language, but it can also be complex and challenging to learn. A cheat sheet for C# can help beginners and experienced programmers alike to quickly reference key concepts and syntax, saving time and reducing the risk of errors.

A brief overview of what will be covered in the cheat sheet

In this cheat sheet, we will cover a range of topics related to C#, from basic syntax and object-oriented programming concepts to collections, input/output, exception handling, LINQ, delegates and events, and asynchronous programming. I'll provide a brief overview of each topic and include examples and code snippets to help you get started with C# programming.

Basics of C#

To write effective code in C#, it's important to first understand the basics. In this section of the ultimate C# cheatsheet, we'll cover the fundamental concepts of the language, including data types, variables, operators, and control flow statements.

Variables Data Types

In C#, variables are used to store data values that can be used and manipulated throughout your program. There are several different data types that you can use in C#, including:

  • int - used to store integer values.
  • float - used to store floating-point values.
  • double - used to store larger floating-point values.
  • bool - used to store true/false values.
  • string - used to store text values.

Here's an example of declaring and using variables in C#:

int myNumber = 10;
float myFloat = 3.14f;
double myDouble = 1.23456789;
bool myBool = true;
string myString = "Hello, world! This is Tech with Christian :)";

Operators

Operators are symbols used to perform mathematical or logical operations on data in a program. C# includes a variety of operators, including arithmetic operators (+, -, *, /), comparison operators (>, <, ==), and logical operators (&&, ||, !). Below are some examples for your reference.

Arithmetic Operators

Arithmetic operators are used to performing mathematical operations such as addition, subtraction, multiplication, and division. Here are some examples of arithmetic operators in C#:

int a = 10;
int b = 5;

int sum = a + b;    // addition
int difference = a - b;    // subtraction
int product = a * b;    // multiplication
int quotient = a / b;    // division
int remainder = a % b;    // modulus (returns the remainder of a division operation)

Comparison Operators

Comparison operators are used to compare two values and return a boolean value ( true or false ) based on the comparison. Here are some examples of comparison operators in C#:

int a = 10;
int b = 5;

bool isEqual = a == b;    // equal to
bool isNotEqual = a != b;    // not equal to
bool isGreater = a > b;    // greater than
bool isLess = a < b;    // less than
bool isGreaterOrEqual = a >= b;    // greater than or equal to
bool isLessOrEqual = a <= b;    // less than or equal to

Logical Operators

Logical operators are used to performing logical operations on boolean values. Here are some examples of logical operators in C#:

bool a = true;
bool b = false;

bool andResult = a && b;    // logical AND
bool orResult = a || b;    // logical OR
bool notResult = !a;    // logical NOT

Assignment Operators

Assignment operators are used to assigning a value to a variable. Here are some examples of assignment operators in C#:

int a = 10;
int b = 5;

a += b;    // equivalent to a = a + b
a -= b;    // equivalent to a = a - b
a *= b;    // equivalent to a = a * b
a /= b;    // equivalent to a = a / b
a %= b;    // equivalent to a = a % b

These are just a few examples of the many operators available in C#. By understanding and mastering these operators, you'll be able to perform a wide variety of operations on variables and values in your C# programs.

Control Flow Statements

Control flow statements are used to control the flow of execution in a program. In C#, there are several control flow statements, including if-else statements, switch statements, and loops ( for, while, and do-while ).

int myNumber = 10;

if (myNumber < 5)
{
    Console.WriteLine("The number is less than 5");
}
else if (myNumber > 15)
{
    Console.WriteLine("The number is greater than 15");
}
else
{
    Console.WriteLine("The number is between 5 and 15");
}

Another common control structure is the for loop, which allows you to iterate through a set of values a certain number of times. Here's an example with a for loop:

for (int i = 0; i < 10; i++)
{
    Console.WriteLine("The value of i is: " + i);
}

Functions

Functions are blocks of code that can be called from other parts of your program. They are useful for organizing your code and making it more reusable. Here's an example of a function that takes two integer parameters and returns their sum:

int AddNumbers(int a, int b)
{
    return a + b;
}

You can call this function from other parts of your code like this:

int result = AddNumbers(10, 5);
Console.WriteLine("The result is: " + result);

Understanding these basic concepts is essential for writing effective C# code. By mastering the basics, you'll be able to write more complex programs with confidence.

Object-Oriented Programming in C#

Object-oriented programming (OOP) is a programming paradigm that emphasizes the use of objects, classes, and inheritance to organize and structure code. C# is an object-oriented language and supports all the features of OOP. In this section of the ultimate C# cheatsheet, we'll cover the key concepts of OOP in C#, along with some code examples.

Classes and Objects

In C#, a class is a blueprint for creating objects. A class defines the properties and methods of an object, and an object is an instance of a class. Objects are used to store data and perform operations on that data.

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    
    public void SayHello()
    {
        Console.WriteLine($"Hello, my name is {Name} and I'm {Age} years old.");
    }
}

Person john = new Person();
john.Name = "John";
john.Age = 30;
john.SayHello(); // Output: Hello, my name is John and I'm 30 years old.

Inheritance

Inheritance is a key feature of OOP (Object Oriented Programming) that allows one class to inherit properties and methods from another class. In C#, a class can inherit from a single base class but can implement multiple interfaces.

class Animal
{
    public string Name { get; set; }
    
    public void Eat()
    {
        Console.WriteLine($"{Name} is eating.");
    }
}

class Dog : Animal
{
    public void Bark()
    {
        Console.WriteLine($"{Name} is barking.");
    }
}

Dog fido = new Dog();
fido.Name = "Fido";
fido.Eat(); // Output: Fido is eating.
fido.Bark(); // Output: Fido is barking.

Polymorphism

Polymorphism is the ability of an object to take on many forms. In C#, polymorphism can be achieved through method overriding, where a subclass provides its own implementation of a method inherited from its parent class.

class Shape
{
    public virtual void Draw()
    {
        Console.WriteLine("Drawing a shape.");
    }
}

class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a circle.");
    }
}

class Square : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a square.");
    }
}

Shape shape1 = new Circle();
shape1.Draw(); // Output: Drawing a circle.

Shape shape2 = new Square();
shape2.Draw(); // Output: Drawing a square.

Abstraction

Abstraction is the process of hiding unnecessary details while showing only the essential features of an object. In C#, abstraction can be achieved through abstract classes and interfaces.

abstract class Animal
{
    public abstract string Name { get; set; }
    public abstract void MakeSound();
}

class Dog : Animal
{
    public override string Name { get; set; }

    public override void MakeSound()
    {
        Console.WriteLine("Woof!");
    }
}

Animal dog = new Dog();
dog.Name = "Fido";
dog.MakeSound(); // Output: Woof!

Encapsulation

Encapsulation is the practice of restricting access to certain components of an object to prevent unwanted changes. In C#, encapsulation can be achieved through access modifiers such as public, private, and protected.

class BankAccount
{
    private double balance;
    
    public void Deposit(double amount)
    {
        balance += amount;
    }

    public void Withdraw(double amount)
    {
        if (balance >= amount)
        {
            balance -= amount;
        }
    }
    
    public double GetBalance()
    {
        return balance;
    }
}

BankAccount account = new BankAccount();
account.Deposit(1000);
account.Withdraw(500);
double balance = account.GetBalance(); // balance is 500

C# Collections

Collections in C# are used to store groups of related objects. There are several types of collections available in C#, including arrays, lists, dictionaries, and sets.

Arrays

An array is a collection of elements of the same type. The length of an array is fixed and cannot be changed once it is created.

int[] numbers = new int[3] { 1, 2, 3 };
Console.WriteLine(numbers[0]); // Output: 1
Console.WriteLine(numbers[1]); // Output: 2
Console.WriteLine(numbers[2]); // Output: 3

Lists

A list is a dynamic collection of elements of the same type. Unlike arrays, the length of a list can be changed after it is created.

List<string> names = new List<string>();
names.Add("Alice");
names.Add("Bob");
names.Add("Charlie");
Console.WriteLine(names[1]); // Output: Bob
names.Remove("Charlie");
Console.WriteLine(names.Count); // Output: 2

Dictionaries

A dictionary is a collection of key-value pairs. Each key must be unique, and the value associated with a key can be any type.

Dictionary<string, int> ages = new Dictionary<string, int>();
ages.Add("Alice", 25);
ages.Add("Bob", 30);
ages.Add("Charlie", 35);
Console.WriteLine(ages["Bob"]); // Output: 30
ages.Remove("Charlie");
Console.WriteLine(ages.Count); // Output: 2

Sets

A set is a collection of unique elements. In C#, sets are implemented using the HashSet class.

HashSet<int> numbers = new HashSet<int>();
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
numbers.Add(3); // Adding a duplicate value has no effect
Console.WriteLine(numbers.Count); // Output: 3
numbers.Remove(2);
Console.WriteLine(numbers.Count); // Output: 2

I have used HashSets to make sure that I got a list of unique items without any duplicates. Let's say you have a large collection of data and you want to remove duplicates from it. One way to do this is to iterate through the collection and add each item to a HashSet. Since a HashSet can only contain unique values, any duplicates will automatically be removed.

using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        // Create a list with some duplicate values
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 2, 3, 6, 7, 1 };

        // Create a HashSet and add all the numbers to it
        HashSet<int> uniqueNumbers = new HashSet<int>();
        foreach (int number in numbers)
        {
            uniqueNumbers.Add(number);
        }

        // Print out the unique numbers
        foreach (int number in uniqueNumbers)
        {
            Console.WriteLine(number);
        }
    }
}

In this example, I create a List of integers with some duplicate values. I then create a HashSet and add all the numbers to it using a foreach loop. Since the HashSet can only contain unique values, any duplicates are automatically removed. Finally, we iterate over the HashSet and print out the unique numbers.

Exception Handling in C#

In C#, exceptions are used to handle runtime errors that occur during program execution. Exception handling allows developers to gracefully handle errors and prevent program crashes.

Try-Catch Blocks

A try-catch block is used to handle exceptions in C#. The code that might generate an exception is placed inside the try block, and any exceptions that are thrown are caught and handled by the catch block.

try
{
    int x = 0;
    int y = 10 / x; // This will throw a DivideByZeroException
}
catch (DivideByZeroException e)
{
    Console.WriteLine("Error: " + e.Message);
}

Finally Block

A finally block can be used to execute code that should always be run, regardless of whether an exception is thrown or not.

try
{
    // Code that might throw an exception
}
catch (Exception e)
{
    Console.WriteLine("Error: " + e.Message);
}
finally
{
    // Code that should always be run
}

Throwing Exceptions

In C#, developers can also explicitly throw exceptions using the throw keyword. This can be useful when custom error handling is needed.

try
{
    string input = Console.ReadLine();
    if (string.IsNullOrEmpty(input))
    {
        throw new Exception("Input cannot be empty.");
    }
}
catch (Exception e)
{
    Console.WriteLine("Error: " + e.Message);
}

Custom Exceptions

Developers can also create custom exception classes to handle specific types of errors.

public class CustomException : Exception
{
    public CustomException(string message) : base(message)
    {
    }
}

try
{
    int x = 0;
    int y = 10 / x;
    throw new CustomException("Custom exception message.");
}
catch (CustomException e)
{
    Console.WriteLine("Error: " + e.Message);
}

File Input and Output in C#

C# provides a set of classes and methods that can be used to read from and write to files. This can be useful when working with data that needs to be persisted beyond the lifetime of the program.

Reading from a File

The StreamReader class can be used to read data from a file. The code below demonstrates how to read all lines from a text file using StreamReader:

using (StreamReader reader = new StreamReader("file.txt"))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        Console.WriteLine(line);
    }
}

Writing to a File

The StreamWriter class can be used to write data to a file. The code below demonstrates how to write a string to a text file using StreamWriter:

using (StreamWriter writer = new StreamWriter("file.txt"))
{
    writer.WriteLine("Hello, world!");
}

Appending to a File

To append to an existing file instead of overwriting it, pass true as the second argument to the StreamWriter constructor:

using (StreamWriter writer = new StreamWriter("file.txt", true))
{
    writer.WriteLine("This line will be appended to the file.");
}

Binary Files

Binary files contain data that is not in human-readable form, such as images or audio files. The BinaryReader and BinaryWriter classes can be used to read and write binary data to a file. The code below demonstrates how to write binary data to a file:

using (BinaryWriter writer = new BinaryWriter(File.Open("file.bin", FileMode.Create)))
{
    byte[] data = { 0x00, 0x01, 0x02, 0x03 };
    writer.Write(data);
}

To read binary data from a file, use the BinaryReader class:

using (BinaryReader reader = new BinaryReader(File.Open("file.bin", FileMode.Open)))
{
    byte[] data = reader.ReadBytes(4);
    Console.WriteLine(BitConverter.ToString(data));
}

LINQ in C#

Language-Integrated Query (LINQ) is a powerful feature in C# that allows developers to query data from various sources using a common syntax. LINQ can be used with objects, arrays, collections, and databases.

LINQ Syntax

The basic syntax of a LINQ query consists of three parts: the source of data, the query operation, and the result.

var result = from item in source
             where condition
             select item;

Filtering Data

In this example, we will use LINQ to filter a list of integers.

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

var result = from num in numbers
             where num % 2 == 0
             select num;

foreach (int num in result)
{
    Console.WriteLine(num);
}

This will output the following:

2
4

Projecting Data

In this example, we will use LINQ to project a list of strings to uppercase.

List<string> words = new List<string> { "hello", "world" };

var result = from word in words
             select word.ToUpper();

foreach (string word in result)
{
    Console.WriteLine(word);
}

This will output the following:

HELLO
WORLD

Joining Data

In this example, we will use LINQ to join two lists of objects.

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

List<Person> people = new List<Person>
{
    new Person { Name = "Alice", Age = 25 },
    new Person { Name = "Bob", Age = 30 },
    new Person { Name = "Charlie", Age = 35 }
};

List<string> cities = new List<string> { "Amsterdam", "Berlin", "Chicago" };

var result = from person in people
             join city in cities on person.Name[0] equals city[0]
             select new { Name = person.Name, City = city };

foreach (var item in result)
{
    Console.WriteLine(item.Name + " - " + item.City);
}

This will output the following:

Alice - Amsterdam
Bob - Berlin
Charlie - Chicago

Multithreading in C#

Multithreading is the process of executing multiple threads concurrently in a single process. Threads allow a program to perform multiple tasks at the same time, improving performance and responsiveness.

Threading Basics

A thread is a path of execution within a program. Every process has at least one thread, the main thread, which is created automatically when the process starts. Additional threads can be created to perform tasks in parallel with the main thread.

In other words. Threads are used to perform multiple tasks simultaneously in a program. By using threads, a program can achieve concurrency, which means that it can do multiple things at the same time. This can lead to improved performance and better responsiveness of the program, especially in cases where the program performs a lot of blocking or time-consuming operations. Below are two examples for you

  1. You are building a file-sharing application that allows users to upload and download files. When a user uploads a large file, the application may take a long time to process it. Without using threads, the application may become unresponsive to other users until the upload process is complete. However, if you use threads to handle file uploads, the user can continue to use the application while the upload is being processed in the background.
  2. A web server that needs to handle multiple requests simultaneously. By using threads, the web server can create a new thread for each incoming request and handle them concurrently, improving the server's overall performance.

Creating and Starting Threads

In C#, you can create and start a new thread using the Thread class.

void DoWork()
{
    // Perform some work
}

Thread thread = new Thread(new ThreadStart(DoWork));
thread.Start();

This will create a new thread and start executing the DoWork method in the background.

Synchronization

When multiple threads access shared resources, there is a risk of data corruption and race conditions. To prevent this, synchronization techniques can be used to ensure that only one thread can access a shared resource at a time.

One common technique for synchronization is the use of locks.

class Counter
{
    private int count = 0;
    private object lockObject = new object();

    public void Increment()
    {
        lock (lockObject)
        {
            count++;
        }
    }

    public int Count
    {
        get { return count; }
    }
}

Counter counter = new Counter();

Thread thread1 = new Thread(() =>
{
    for (int i = 0; i < 1000000; i++)
    {
        counter.Increment();
    }
});

Thread thread2 = new Thread(() =>
{
    for (int i = 0; i < 1000000; i++)
    {
        counter.Increment();
    }
});

thread1.Start();
thread2.Start();

thread1.Join();
thread2.Join();

Console.WriteLine(counter.Count);

This will output 2000000, which is the expected result since both threads are incrementing the counter one million times each.

Thread Safety

Thread safety is the property of an object or method that ensures that it can be safely used by multiple threads at the same time without causing data corruption or race conditions.

One way to achieve thread safety is through the use of the lock keyword, as demonstrated in the previous example. Another way is to use immutable objects, which cannot be modified once they are created.

class ImmutableCounter
{
    private readonly int count = 0;

    public ImmutableCounter(int count)
    {
        this.count = count;
    }

    public ImmutableCounter Increment()
    {
        return new ImmutableCounter(count + 1);
    }

    public int Count
    {
        get { return count; }
    }
}

ImmutableCounter counter = new ImmutableCounter(0);

Thread thread1 = new Thread(() =>
{
    for (int i = 0; i < 1000000; i++)
    {
        counter = counter.Increment();
    }
});

Thread thread2 = new Thread(() =>
{
    for (int i = 0; i < 1000000; i++)
    {
        counter = counter.Increment();
    }
});

thread1.Start();
thread2.Start();

thread1.Join();
thread2.Join();

Console.WriteLine(counter.Count);

This will output 2000000, which is the expected result since both threads are creating new instances of the ImmutableCounter object and incrementing the count. Since the object is immutable, there is no risk of data corruption or race conditions.

Using threads can make a program more responsive, improve its performance, and allow it to perform multiple tasks simultaneously, which can be essential in certain types of applications.

Advanced C# Features

C# is a powerful and versatile programming language that includes a variety of advanced features to help you write efficient, flexible, and maintainable code. Here are some of the most useful advanced features of C#, along with code examples to illustrate how they work.

Delegates

A delegate is a type that represents a method signature, allowing you to pass methods as arguments to other methods or store them as variables. Delegates are commonly used in event handling and callback scenarios.

public delegate void MyDelegate(string message);

public class MyClass
{
    public event MyDelegate MyEvent;

    public void RaiseEvent(string message)
    {
        MyEvent?.Invoke(message);
    }
}

public class Program
{
    public static void Main()
    {
        MyClass myClass = new MyClass();
        myClass.MyEvent += MyEventHandler;
        myClass.RaiseEvent("Hello, world!");
    }

    public static void MyEventHandler(string message)
    {
        Console.WriteLine(message);
    }
}

This code creates a custom delegate type MyDelegate, and then defines a class MyClass with an event of that type. In the Main method, we create an instance of MyClass, attach a method MyEventHandler to the event, and then raise the event with a message. The MyEventHandler method is called and prints the message to the console.

Extension Methods

Extension methods allow you to add methods to an existing class without modifying its source code. This is useful when you want to add functionality to a class that you don't have control over, or when you want to group related functionality into a single class.

public static class StringExtensions
{
    public static bool IsPalindrome(this string str)
    {
        for (int i = 0; i < str.Length / 2; i++)
        {
            if (str[i] != str[str.Length - i - 1])
            {
                return false;
            }
        }
        return true;
    }
}

public class Program
{
    public static void Main()
    {
        string str1 = "racecar";
        string str2 = "hello";

        Console.WriteLine(str1.IsPalindrome());
        Console.WriteLine(str2.IsPalindrome());
    }
}

This code defines a static class StringExtensions with an extension method IsPalindrome, which determines whether a string is a palindrome. We then call this method on two strings in the Main method and print the results to the console.

🤓
A palindrome is a word, phrase, or sentence that reads the same way forwards and backward. For example, "racecar" is a palindrome because if you spell it backward it still says "racecar".

3. Lambda Expressions

Lambda expressions are a concise way to define anonymous methods, allowing you to write code inline without creating a separate method.

public class Program
{
    public static void Main()
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

        List<int> evenNumbers = numbers.Where(n => n % 2 == 0).ToList();

        foreach (int number in evenNumbers)
        {
            Console.WriteLine(number);
        }
    }
}

This code creates a list of integers and then uses a lambda expression to filter out the even numbers using the Where method. We then loop over the even numbers and print them to the console. When would this be useful?

Let's say you have a large collection of numbers, and you need to perform some operation on only the even numbers in the collection. Instead of manually iterating over the collection and checking each number to see if it's even, you can use LINQ to quickly and efficiently filter the collection.

Generics

Generics allow you to write code that can work with multiple data types, improving code reuse and reducing the need for type casting.

public class Stack<T>
{
    private List<T> items = new List<T>();

    public void Push(T item)
    {
        items.Add(item);
    }

    public T Pop()
    {
        T item = items.Last();
        items.RemoveAt(items.Count - 1);
        return item;
    }
}

public class Program
{
    public static void Main()
    {
        Stack<int> stack = new Stack<int>();
        stack.Push(1);
        stack.Push(2);
        stack.Push(3);

        Console.WriteLine(stack.Pop());
        Console.WriteLine(stack.Pop());
        Console.WriteLine(stack.Pop());
    }
}

This code defines a generic Stack class that can hold any data type. We then create an instance of the class with int as the type parameter, push three integers onto the stack, and then pop them off and print them to the console. This could be done for any type.

Async/Await

Async / await is a programming pattern that allows you to write asynchronous code that is easier to read and maintain than traditional callback-based code.

public class Program
{
    public static async Task Main()
    {
        HttpClient httpClient = new HttpClient();
        string response = await httpClient.GetStringAsync("https://jsonplaceholder.typicode.com/todos/1");
        Console.WriteLine(response);
    }
}

This code uses the HttpClient class to make an asynchronous HTTP request to a web API and retrieve some data. We use the async keyword to mark the Main method as asynchronous, and then use the await keyword to wait for the result of the HTTP request before printing it to the console. Below is the result of the API call.

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

Attributes

Attributes are a way to add metadata to your code, allowing you to specify additional information about types, methods, and properties that can be used by tools and libraries.

[Serializable]
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class Program
{
    public static void Main()
    {
        Person person = new Person { Name = "Alice", Age = 30 };

        XmlSerializer serializer = new XmlSerializer(typeof(Person));
        StringWriter writer = new StringWriter();
        serializer.Serialize(writer, person);

        Console.WriteLine(writer.ToString());
    }
}

This code defines a Person class with two properties and marks it with the [Serializable] attribute. We then use the XmlSerializer class to serialize an instance of the Person class to an XML string, which we print to the console.

Reflection

Reflection allows you to inspect and modify your code at runtime, enabling powerful runtime behaviors such as dependency injection and dynamic loading of plugins.

public class MyClass
{
    public int MyProperty { get; set; }

    public void MyMethod(string message)
    {
        Console.WriteLine(message);
    }
}

public class Program
{
    public static void Main()
    {
        MyClass myClass = new MyClass();

        PropertyInfo propertyInfo = typeof(MyClass).GetProperty("MyProperty");
        propertyInfo.SetValue(myClass, 42);

        MethodInfo methodInfo = typeof(MyClass).GetMethod("MyMethod");

If you would like to know more about reflection in .NET, you can have a look at my article below.

Learn To Understand Reflection in .NET in a few minutes
Reflection is used to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object. In this tutorial about reflection in .NET I will break it down into human-readable content with examples.

Summary

In this C# cheat sheet, we covered a range of essential topics in C#, from the basics of the language to advanced features like multithreading and reflection. We've seen how C# supports object-oriented programming through concepts like classes, inheritance, and encapsulation, and we've explored some of the powerful libraries and tools available in C# for handling collections, working with files, and querying data using LINQ.

By mastering these fundamental concepts and features, you'll be well-equipped to tackle a wide range of programming challenges in C# and build powerful, efficient, and scalable applications. Whether you're a seasoned developer or just starting out, C# is a language that has something to offer everyone.

So if you're looking to improve your programming skills and take your C# development to the next level, be sure to continue exploring the language and its many features, and don't be afraid to experiment and push the boundaries of what's possible. With practice and perseverance, you'll soon be writing world-class code that can take on even the most complex programming challenges with ease.