using System;
Includes core system functionality such as Console, Math, String, etc.
using System;
Console.WriteLine("Hello, World!");
using System.Collections.Generic;
Enables usage of generic collections like List
using System.Collections.Generic;
List names = new List();
using System.Linq;
Provides LINQ functionality to query collections using a functional approach.
using System.Linq;
var evenNumbers = numbers.Where(n => n % 2 == 0);
using System.Text;
Gives access to classes for string encoding and StringBuilder.
using System.Text;
StringBuilder sb = new StringBuilder();
using System.Threading;
Provides classes and methods for multithreading.
using System.Threading;
Thread.Sleep(1000);
using System.IO;
Used for file and stream I/O operations.
using System.IO;
File.WriteAllText("file.txt", "Hello");
namespace Declaration
Defines a scope to group related classes and avoid naming conflicts.
namespace MyApplication
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello from MyApplication!");
}
}
}
class Declaration
Defines a class as the core building block of a C# program. Can contain methods, properties, and fields.
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}
Entry Point: static void Main(string[] args)
The starting point of a C# console application. Executes when the program runs.
static void Main(string[] args)
{
Console.WriteLine("Welcome to the program!");
}
Method Declaration
Defines a reusable block of code. Includes access modifiers, return type, method name, and parameters.
public void GreetUser(string name)
{
Console.WriteLine($"Hello, {name}!");
}
Static Method Declaration
A method that belongs to the class itself rather than to instances of the class.
public static int Square(int number)
{
return number * number;
}
if Statement
Executes a block of code if a specified condition is true.
if (score >= 50)
{
Console.WriteLine("You passed!");
}
if-else Statement
Executes one block of code if the condition is true, another block if the condition is false.
if (score >= 50)
{
Console.WriteLine("You passed!");
}
else
{
Console.WriteLine("You failed.");
}
else-if Ladder
Checks multiple conditions in sequence and executes the first true block.
if (score >= 90)
{
Console.WriteLine("Grade: A");
}
else if (score >= 80)
{
Console.WriteLine("Grade: B");
}
else
{
Console.WriteLine("Grade: C or below");
}
switch Statement
Selects one of many code blocks to be executed based on a matching value.
switch (day)
{
case "Monday":
Console.WriteLine("Start of the week!");
break;
case "Friday":
Console.WriteLine("Weekend is near!");
break;
default:
Console.WriteLine("Just another day.");
break;
}
for Loop
Executes a block of code a specific number of times.
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"Iteration {i}");
}
while Loop
Repeats a block of code while a specified condition is true.
int count = 0;
while (count < 3)
{
Console.WriteLine($"Count: {count}");
count++;
}
do-while Loop
Similar to a while loop, but guarantees the block runs at least once.
int number;
do
{
Console.Write("Enter a number (0 to stop): ");
number = int.Parse(Console.ReadLine());
} while (number != 0);
foreach Loop
Iterates over each element in a collection or array.
string[] fruits = {"Apple", "Banana", "Cherry"};
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}
break Statement
Terminates the closest enclosing loop or switch statement immediately.
for (int i = 0; i < 10; i++)
{
if (i == 5)
{
break;
}
Console.WriteLine(i);
}
continue Statement
Skips the current iteration of a loop and continues with the next iteration.
for (int i = 0; i < 5; i++)
{
if (i == 2)
{
continue;
}
Console.WriteLine(i);
}
int
Stores whole numbers between -2,147,483,648 and 2,147,483,647.
int age = 30;
Console.WriteLine(age);
double
Stores decimal numbers with double precision floating point.
double price = 19.99;
Console.WriteLine(price);
bool
Stores true or false values.
bool isActive = true;
Console.WriteLine(isActive);
char
Stores a single Unicode character.
char grade = 'A';
Console.WriteLine(grade);
string
Stores a sequence of characters (text).
string message = "Hello, World!";
Console.WriteLine(message);
var (Implicit Typing)
Infers the type from the assigned value (must be initialized).
var count = 10; // inferred as int
Console.WriteLine(count);
const
Declares an unchangeable (compile-time) constant.
const double Pi = 3.14159;
Console.WriteLine(Pi);
object
Base type of all data types in C#. Can hold any type.
object data = 42;
Console.WriteLine(data);
dynamic
Stores any type and resolves at runtime (no compile-time type checking).
dynamic value = "Hello";
value = 123;
Console.WriteLine(value);
decimal
Precise decimal numbers for financial and monetary calculations.
decimal balance = 1000.75m;
Console.WriteLine(balance);
Method Declaration
Defines a reusable block of code with a return type, name, and optional parameters.
public void SayHello()
{
Console.WriteLine("Hello!");
}
Calling a Method
Invoke a method by using its name followed by parentheses.
SayHello();
Method with Parameters
Pass values to a method using parameters.
public void Greet(string name)
{
Console.WriteLine($"Hello, {name}!");
}
Returning a Value
Methods can return values using a return type and the return keyword.
public int Add(int a, int b)
{
return a + b;
}
Method Overloading
Multiple methods can share the same name if they differ in parameters.
public void Print(string message) { }
public void Print(int number) { }
Default Parameters
Provide default values for parameters so they are optional when calling the method.
public void ShowMessage(string msg = "Default")
{
Console.WriteLine(msg);
}
Static Methods
Belong to the class itself and can be called without an instance.
public static void Log(string message)
{
Console.WriteLine(message);
}
Main Method
The entry point of a C# application. Must be static.
static void Main(string[] args)
{
Console.WriteLine("Program started.");
}
Async Methods
Methods marked with async can use the await keyword for asynchronous operations.
public async Task LoadDataAsync()
{
await Task.Delay(1000);
Console.WriteLine("Done.");
}
ref Parameter
Allows a method to modify the caller’s variable directly.
void Modify(ref int number)
{
number += 10;
}
int val = 5;
Modify(ref val);
out Parameter
Used to return multiple values from a method.
void GetValues(out int x, out int y)
{
x = 10;
y = 20;
}
GetValues(out int a, out int b);
in Parameter
Passes a parameter by reference but does not allow modification.
void Show(in int value)
{
Console.WriteLine(value);
}
params Array
Allows passing a variable number of arguments to a method.
void PrintNumbers(params int[] numbers)
{
foreach (int n in numbers)
Console.WriteLine(n);
}
PrintNumbers(1, 2, 3);
Expression-Bodied Method
Concise method syntax for simple return expressions.
int Square(int x) => x * x;
Extension Method
Adds a method to an existing type without modifying it directly.
public static class StringExtensions
{
public static int WordCount(this string str)
{
return str.Split(' ').Length;
}
}
string s = "Hello world";
int count = s.WordCount();
Local Function
A method defined inside another method.
void Outer()
{
void Inner()
{
Console.WriteLine("Inside Inner");
}
Inner();
}
Class Definition
Defines a blueprint for creating objects with fields, properties, and methods.
public class Person
{
public string Name;
public void Greet() {
Console.WriteLine($"Hello, {Name}!");
}
}
Object Instantiation
Creates an instance of a class using the `new` keyword.
Person p = new Person();
p.Name = "Sam";
p.Greet();
Constructor
Special method that runs when a new object is created.
public class Person
{
public string Name;
public Person(string name) {
Name = name;
}
}
Access Modifiers
Control visibility of class members using `public`, `private`, etc.
public class Car {
private int speed;
public void Accelerate() {
speed += 10;
}
}
this Keyword
Refers to the current instance of the class.
public class Box {
private int width;
public Box(int width) {
this.width = width;
}
}
Auto-Implemented Properties
Simplified syntax for defining public properties with getters/setters.
public class User {
public string Name { get; set; }
}
Static Class
A class that cannot be instantiated and only contains static members.
public static class MathHelper
{
public static int Double(int x)
{
return x * 2;
}
}
int result = MathHelper.Double(4);
Object Initializer
Creates an object and sets its properties in a single expression.
Person p = new Person {
Name = "Alex",
Age = 28
};
Inheritance
Allows a class to inherit fields and methods from another class.
public class Animal {
public void Speak() {
Console.WriteLine("Sound");
}
}
public class Dog : Animal { }
virtual and override
Used to override a method in a derived class.
public class Animal {
public virtual void Speak() {
Console.WriteLine("Sound");
}
}
public class Dog : Animal {
public override void Speak() {
Console.WriteLine("Bark");
}
}
Abstract Class
Cannot be instantiated and may contain abstract (must override) members.
public abstract class Shape {
public abstract double Area();
}
public class Circle : Shape {
public override double Area() => 3.14 * 4 * 4;
}
Interface
Defines a contract. A class must implement all members of the interface.
public interface IDrive {
void Start();
}
public class Car : IDrive {
public void Start() {
Console.WriteLine("Engine on");
}
}
Sealed Class
Prevents a class from being inherited.
public sealed class Config {
public string Name { get; set; }
}
base Keyword
Calls a method or constructor from the parent class.
public class Animal {
public virtual void Speak() {
Console.WriteLine("Sound");
}
}
public class Dog : Animal {
public override void Speak() {
base.Speak();
Console.WriteLine("Bark");
}
}
Polymorphism
Allows objects to be treated as instances of their base type.
Animal animal = new Dog();
animal.Speak(); // Outputs: Bark
Array Declaration
Fixed-size, strongly typed collection of elements.
int[] numbers = new int[] { 1, 2, 3, 4 };
Array Access
Access elements in an array using zero-based indexing.
int first = numbers[0];
Console.WriteLine(first);
List Declaration
A dynamic, strongly typed generic list.
List fruits = new List();
fruits.Add("Apple");
Dictionary
Stores key-value pairs for quick lookups.
Dictionary scores = new Dictionary();
scores["Alice"] = 90;
foreach Loop
Iterates over collections such as arrays or lists.
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}
Collection Initializer
Creates and populates a collection in one statement.
var colors = new List { "Red", "Green", "Blue" };
Access List Elements
Use indexers to access elements from a list.
string firstColor = colors[0];
Enum Definition
Defines a set of named integral constants.
enum Status {
Pending,
Approved,
Rejected
}
Using an Enum
Use enum values like strongly typed constants.
Status current = Status.Approved;
Console.WriteLine(current);
Enum with Explicit Values
You can assign specific values to enum members.
enum Day {
Sunday = 1,
Monday = 2
}
Struct Definition
A lightweight value type often used for small data models.
struct Point {
public int X;
public int Y;
}
Using a Struct
Create and use a struct like an object, but it’s passed by value.
Point p = new Point();
p.X = 5;
p.Y = 10;
Enum to Int
Enums can be cast to their underlying integer values.
int code = (int)Status.Approved;
Console.WriteLine(code);
[Flags] Enum
Allows combining enum values using bitwise operations.
[Flags]
enum Permissions {
None = 0,
Read = 1,
Write = 2,
Execute = 4
}
Permissions p = Permissions.Read | Permissions.Write;
readonly struct
Prevents modification of struct fields after creation, improving performance and immutability.
public readonly struct Coordinate {
public int X { get; }
public int Y { get; }
public Coordinate(int x, int y) {
X = x;
Y = y;
}
}
try-catch Block
Catches and handles exceptions thrown during execution.
try {
int x = 10 / 0;
} catch (DivideByZeroException ex) {
Console.WriteLine("Cannot divide by zero.");
}
try-catch-finally
finally block runs regardless of whether an exception is thrown.
try {
// risky code
} catch (Exception ex) {
Console.WriteLine(ex.Message);
} finally {
Console.WriteLine("Cleanup");
}
throw Keyword
Throws a new or rethrows an existing exception.
if (input == null) {
throw new ArgumentNullException(nameof(input));
}
Custom Exception
You can define your own exception class by extending Exception.
public class MyException : Exception {
public MyException(string msg) : base(msg) {}
}
Multiple catch Blocks
You can catch different exception types with multiple catch blocks.
try {
// code
} catch (IOException ex) {
// file error
} catch (Exception ex) {
// general
}
Rethrow Exception
Use `throw;` to pass the exception up the call stack.
try {
// code
} catch (Exception ex) {
Log(ex);
throw;
}
catch with when Filter
Adds a condition to a catch block using `when`.
try {
// risky operation
} catch (IOException ex) when (ex.Message.Contains("disk")) {
Console.WriteLine("Disk-related IO error.");
}
ExceptionDispatchInfo.Capture
Preserves original exception stack trace when rethrowing.
try {
throw new InvalidOperationException();
} catch (Exception ex) {
var edi = ExceptionDispatchInfo.Capture(ex);
// log or handle
edi.Throw();
}
Namespace Definition
Organizes classes and types into logical groups.
namespace MyApp.Utilities {
class Logger {
// ...
}
}
Nested Namespaces
Defines namespaces inside another to represent hierarchy.
namespace Company.Project.Module {
class Service {}
}
using Namespace
Imports types from a namespace to use without full qualification.
using System.Text;
StringBuilder sb = new StringBuilder();
Namespace Alias
Defines an alias for a namespace to shorten long references.
using Utils = MyCompany.Tools.Utilities;
Utils.Logger.Log("Done");
Global Namespace
Use `global::` to explicitly refer to the root namespace.
global::System.Console.WriteLine("Hello");
const Keyword
Defines a compile-time constant value.
const double Pi = 3.14159;
Console.WriteLine(Pi);
readonly Field
A field that can only be assigned during declaration or in a constructor.
class Circle {
public readonly double Radius;
public Circle(double r) {
Radius = r;
}
}
static readonly
Shared across all instances and set once at runtime.
public static readonly string AppName = "Cheatsheet";
const vs readonly
const is compile-time; readonly is runtime-settable (in constructor).
// const: compile-time
const int MaxUsers = 100;
// readonly: runtime
readonly Guid Id = Guid.NewGuid();
Nullable Value Type
Use `?` to allow value types to hold `null`.
int? age = null;
if (age.HasValue) {
Console.WriteLine(age.Value);
}
?? Null Coalescing
Provides a default value if the left-hand operand is null.
string name = inputName ?? "Guest";
?. Null Conditional
Safely access members without throwing if the target is null.
Console.WriteLine(user?.Profile?.Name);
! Null Forgiving
Suppresses compiler warnings about nullability.
string definitelyNotNull = maybeNull!;
Nullable Reference Types
Enable nullable reference types to get static analysis support.
#nullable enable
string? name = null;
Console.WriteLine(name?.Length);
Implicit Casting
Automatically converts smaller types to larger compatible types.
int num = 10;
double result = num; // Implicit cast
Explicit Casting
Manually convert types that require confirmation (may lose data).
double d = 9.8;
int i = (int)d;
as Keyword
Attempts a safe cast to a reference type or nullable type, returns null if it fails.
object obj = "hello";
string str = obj as string;
is Keyword
Checks if an object is of a specific type.
if (obj is string s) {
Console.WriteLine(s);
}
Convert Class
Provides methods to convert between base types safely.
string str = "123";
int num = Convert.ToInt32(str);
TryParse Method
Safely attempts to parse a string into a type without throwing exceptions.
if (int.TryParse("42", out int result)) {
Console.WriteLine(result);
}
[Obsolete] Attribute
Marks a method or class as outdated; shows a compile warning or error.
[Obsolete("Use NewMethod instead")]
void OldMethod() {
// ...
}
Declaring an Attribute
Attributes are applied with square brackets above declarations.
[Serializable]
class MyData {
public int Id;
}
Custom Attribute
Create a new attribute by extending System.Attribute.
public class AuthorAttribute : Attribute {
public string Name;
public AuthorAttribute(string name) {
Name = name;
}
}
Multiple Attributes
You can apply multiple attributes using commas or multiple brackets.
[Serializable, Obsolete]
class OldClass {}
Targeted Attribute
Attributes can be directed to specific parts like return types.
[return: NotNull]
public string? GetName() => name;
Basic Lambda
A concise way to represent an anonymous method.
Func square = x => x * x;
Console.WriteLine(square(5));
Lambda with Multiple Parameters
Use parentheses for multiple parameters.
Func add = (a, b) => a + b;
Console.WriteLine(add(2, 3));
Lambda with Block Body
Use braces for multiple statements or return logic.
Func doubleIt = x => {
Console.WriteLine(x);
return x * 2;
};
Lambda in LINQ
Lambdas are frequently used in LINQ queries.
var evens = numbers.Where(n => n % 2 == 0).ToList();
Action Delegate
Use `Action` when the lambda does not return a value.
Action greet = name => Console.WriteLine($"Hello, {name}");
greet("Sam");
is Pattern Matching
Checks type and declares variable if matched.
if (obj is string s) {
Console.WriteLine(s.Length);
}
switch Expression Pattern
Pattern match using modern `switch` expressions.
string result = value switch {
1 => "One",
2 => "Two",
_ => "Other"
};
Relational Pattern
Match based on comparisons like `<`, `>=`, etc.
string msg = number switch {
< 0 => "Negative",
0 => "Zero",
> 0 => "Positive"
};
Logical Patterns
Combine patterns with `and`, `or`, and `not`.
if (x is > 0 and < 100) {
Console.WriteLine("In range");
}
Type Pattern with Property
Use nested patterns to check properties inline.
if (person is { Age: > 18 }) {
Console.WriteLine("Adult");
}
Basic Tuple
A lightweight way to return multiple values.
var person = ("Alice", 30);
Console.WriteLine(person.Item1);
Named Tuple
Name tuple fields for more readable code.
var person = (Name: "Alice", Age: 30);
Console.WriteLine(person.Name);
Return Tuple from Method
Use tuples to return multiple values from methods.
public (int sum, int diff) Calc(int a, int b) {
return (a + b, a - b);
}
Deconstruct Tuple
Split tuple elements into separate variables.
var (name, age) = ("Bob", 25);
Console.WriteLine(name);
Deconstruct Custom Object
Define `Deconstruct` method to enable tuple-style unpacking.
public void Deconstruct(out string name, out int age) {
name = this.Name;
age = this.Age;
}
dynamic Type
Bypasses compile-time type checking and resolves members at runtime.
dynamic message = "Hello";
Console.WriteLine(message.ToUpper());
Dynamic Behavior
Supports interop scenarios, reflection, and COM object manipulation.
dynamic excel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
excel.Visible = true;
ExpandoObject
Allows you to dynamically add members to an object at runtime.
dynamic person = new ExpandoObject();
person.Name = "Jane";
person.Age = 28;
ExpandoObject with Method
You can attach delegates to `ExpandoObject` members.
person.Speak = (Action)(() => Console.WriteLine("Hi!"));
person.Speak();
#if / #endif
Conditionally compile code blocks based on symbols.
#define DEBUG
#if DEBUG
Console.WriteLine("Debug Mode");
#endif
#define Directive
Defines a symbol for conditional compilation.
#define FEATURE_X
#if FEATURE_X
Console.WriteLine("Feature Enabled");
#endif
#region / #endregion
Organizes code into collapsible blocks in editors.
#region Utility Methods
void Log(string msg) {
Console.WriteLine(msg);
}
#endregion
#warning / #error
Generates compile-time warnings or errors.
#warning Deprecated API usage
#error Critical failure
#pragma warning
Disables or restores specific compiler warnings.
#pragma warning disable CS0168
int unused;
#pragma warning restore CS0168
Auto-Implemented Property
Simplifies property declaration with an implicit backing field.
public string Name { get; set; }
Custom Property
Define logic in `get` and `set` accessors.
private int _age;
public int Age {
get => _age;
set {
if (value >= 0) _age = value;
}
}
Read-Only Property
Property with a `get` accessor only (no `set`).
public DateTime Created { get; } = DateTime.Now;
Init-Only Property
Allows assignment during object initialization only.
public string Title { get; init; }
Basic Indexer
Allow objects to be accessed like arrays.
public string this[int index] {
get => items[index];
set => items[index] = value;
}
unsafe Keyword
Marks a block of code as unsafe for pointer operations.
unsafe {
int* p = &number;
Console.WriteLine(*p);
}
fixed Statement
Pins a variable in memory to prevent GC from moving it.
fixed (int* p = &array[0]) {
Console.WriteLine(*p);
}
Pointer Declaration
Declares a pointer using the `*` symbol.
int* ptr;
int value = 10;
ptr = &value;
stackalloc
Allocates memory on the stack instead of the heap.
Span numbers = stackalloc int[5];
Enable Unsafe Code
Must be enabled in project settings to use unsafe code.
// In .csproj file
true
Console.WriteLine()
Writes a line to the console and moves to the next line.
Console.WriteLine("Hello, world!");
Console.Write()
Writes text to the console without a newline.
Console.Write("Enter value: ");
Console.WriteLine with Format String
Writes formatted values using placeholders like {0}.
Console.WriteLine("Name: {0}, Age: {1}", name, age);
Console.Write with Format String
Writes formatted text without a newline.
Console.Write("X = {0}", x);
String Interpolation
Embeds expressions inside string literals using `$` prefix.
Console.WriteLine($"Hello, {name}! You are {age} years old.");
String.Format()
Formats a string with placeholders, returns a result string.
var message = String.Format("{0} scored {1} points.", player, score);
Console.WriteLine(message);
Debug.WriteLine
Writes diagnostic messages to the Output window in debug mode.
using System.Diagnostics;
Debug.WriteLine("Debug message");
Trace.WriteLine
Outputs messages that remain in production builds if trace is enabled.
using System.Diagnostics;
Trace.WriteLine("Trace message");
Debug.Assert
Checks a condition and displays a dialog if the condition is false (only in debug mode).
Debug.Assert(user != null, "User should not be null");
Trace Listeners
Redirect trace output to files, logs, or other destinations using listeners.
Trace.Listeners.Add(new TextWriterTraceListener("log.txt"));
Trace.AutoFlush = true;
Trace.WriteLine("Logging to file");
TraceSwitch
Controls tracing behavior via configuration or code.
TraceSwitch ts = new TraceSwitch("General", "Entire App");
if (ts.TraceInfo) Trace.WriteLine("Info message");
Console Logging
Use `Console.WriteLine` or `Console.Error.WriteLine` for simple logs in small apps.
Console.WriteLine("[INFO] Operation started");
Console.Error.WriteLine("[ERROR] Something went wrong");
Trace Logging
Use `System.Diagnostics.Trace` to send logs to listeners like files or logs.
using System.Diagnostics;
Trace.WriteLine("[TRACE] Application started");
Trace.TraceError("[ERROR] Critical failure");
Debug vs Trace
`Debug` logs are only active in Debug builds. `Trace` works in all builds with listeners.
Debug.WriteLine("[DEBUG] This only appears in debug mode");
Trace.WriteLine("[TRACE] This works in any build");
Structured Logging (Serilog)
Use Serilog or similar libraries for structured logs with metadata and output formats.
// Example with Serilog
Log.Information("Order processed {@Order}", order);
WriteAllText
Writes text to a file, replacing any existing content.
File.WriteAllText("output.txt", "Hello, file!");
AppendAllText
Appends text to the end of a file.
File.AppendAllText("output.txt", "\nMore data.");
StreamWriter
Provides advanced control over writing to files.
using (var writer = new StreamWriter("output.txt")) {
writer.WriteLine("Line 1");
writer.WriteLine("Line 2");
}
WriteAllLines
Writes an array of strings to a file, one line each.
string[] lines = { "Line A", "Line B" };
File.WriteAllLines("log.txt", lines);
AppendAllLines
Appends lines of text to a file from an array.
string[] extra = { "Line C", "Line D" };
File.AppendAllLines("log.txt", extra);
CreateText
Creates or overwrites a file and returns a StreamWriter.
using var writer = File.CreateText("data.txt");
writer.WriteLine("New file content.");
String Interpolation
Embed expressions directly in string literals using `$` syntax.
string name = "Sam";
int age = 30;
string output = $"{name} is {age} years old.";
Composite Formatting
Uses numbered placeholders to insert values in strings.
string result = string.Format("{0} is {1} years old.", "Sam", 30);
Composite Formatting
Uses numbered placeholders to insert values in strings.
string result = string.Format("{0} is {1} years old.", "Sam", 30);
ToString Format Specifiers
Apply numeric or date formats using ToString.
DateTime now = DateTime.Now;
string formatted = now.ToString("yyyy-MM-dd");
String.Format with Specifiers
Combine composite formatting and format specifiers.
double price = 123.456;
string text = string.Format("Price: {0:C2}", price);
Verbatim String Literals
Use @ to avoid escaping backslashes and newlines.
string path = @"C:\Users\John\Documents\file.txt";
Escape Sequences
Use escape characters like \n, \t for formatting.
Console.WriteLine("Line1\nLine2\tIndented");
Escape Sequences
Use escape characters like \n, \t for formatting.
Console.WriteLine("Line1\nLine2\tIndented");
Set Foreground Color
Change the console text color using Console.ForegroundColor.
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Success!");
Console.ResetColor();
Set Background Color
Customize the console background color.
Console.BackgroundColor = ConsoleColor.DarkBlue;
Console.WriteLine("Notice");
Console.ResetColor();
Custom TextWriter
Redirect output by creating a custom TextWriter and assigning it to Console.SetOut.
using (var writer = new StreamWriter("log.txt"))
{
Console.SetOut(writer);
Console.WriteLine("Logging to file");
}
Write to MemoryStream
Use MemoryStream with StreamWriter for temporary, in-memory output.
using var mem = new MemoryStream();
using var writer = new StreamWriter(mem);
writer.Write("Hello in memory");
writer.Flush();