C# is an object-oriented language, which means the unit you work in is the type. A class describes what something is and what it can do, an interface describes only what it can do, and an object is one live instance of a class sitting in memory.
The four ideas underneath all of it are encapsulation (hide the inside), inheritance (build a type from another type), polymorphism (one call, several behaviours) and abstraction (name the idea, not the implementation). Every article on this page is one of those four ideas applied to a real problem.
C# has also grown a lot of type kinds since it started. Alongside class and struct you now have record, record struct, tuple and ValueTuple, and the one you pick changes how your code behaves. There is a section below on it.
This is the biggest topic on the blog, so use the sections. Start at the top if you are learning, or jump to whichever one matches what you are stuck on.
Classes, Objects and Constructors
The starting point: declaring a type and getting an instance of it.
- Readonly Modifier
- Object Initializers
- Boosting Performance With Sealed Classes
- When to Use Static Classes
- Deep Dive into Conversions in C# With the Convert Class
- Differences Between Record Struct and Record Class
- Access Modifiers
- Abstract Classes
- Partial Classes In C# And How to Use Them
- Should We Use Records or Classes or Structs
- Constructor Overloading
- Classes and Constructors
- Constructors
- Primary Constructors for Classes and Structs
- Working With Guid
- How to Create a Class Dynamically
Properties and Fields
How a type exposes its state, and the difference between the two ways of doing it.
- Init Only Setters
- What Is the Difference Between Properties and Fields
- Properties
- The Best Way to Assign an Initial Value to Auto-Properties
- Indexers
- Extended Property Patterns
- How to Ignore a Property in AutoMapper
- How to Resolve Non-nullable Property Must Contain a Non-null Value Warning
- How to Get a Value of a Property By Using its Name
- Represent the Relationship of Properties Using Property Mappings From AutoMapper
Methods, Parameters and Overloading
Everything about calling code: how many arguments, what comes back, and which overload actually runs.
- Method Overriding
- Virtual vs Abstract Methods
- Virtual Methods
- Differences Between Any and Exists Methods
- Methods
- Static Methods vs. Non-Static Methods
- Params Keyword
- Method Overloading
- Lambda Expressions
- Local Functions vs Lambda Expressions
- Named Arguments and Optional Parameters
- Differences Between Equality Operator (==) And Equals Method
- Expression-bodied Members
- Static Members, Constants and Extension Methods
- Local Functions
- Default Interface Method in C# And When to Use It
- Default Values for Lambda Expressions
- How to Mark Methods as Deprecated
- How to Return null From a Generic Method
- Comparing ForEach Method and Foreach Statement
- How to Find the Caller Method
- Using a Discard Variable
- Return Multiple Values to a Method Caller
- Using Static Anonymous Functions
Inheritance, Interfaces and Polymorphism
The part of OOP people argue about. These articles include when not to inherit.
- Upcasting and Downcasting
- Composition vs Inheritance
- Difference Between Abstraction and Encapsulation
- Types of Inheritance
- Polymorphism
- Inheritance
- Interfaces
- How to Correctly Implement IDisposable Interface
Records, Structs, Tuples and Anonymous Types
Choosing between the type kinds C# now gives you.
- Difference Between ValueTuple and Tuple
- Tuple Aliases
- Tuple
- Records
- Anonymous Types
- Anonymous and Nullable Types
- Structures
- Linear Structures, Input and Output
- How to Initialize Parameters of a Record
Generics, Delegates and Events
Writing a type once and using it with many other types, and letting objects notify each other.
- Generic Attributes
- IComparable vs IComparer vs Comparison Delegate
- Covariance and Contravariance
- Invariance, Contravariance and Covariance in Generics
- Events
- Weak Events
- Generics
- Delegates (C# Intermediate Series)
- Delegates
- Using Generics
Enums and Constants
Named values, and the difference between a value fixed at compile time and one fixed at construction.
- Flags Attribute For Enum
- Differences Between Const and Readonly
- Enumerations
- How to Check the Total Number of Items Defined in an Enum
- How to Enumerate an Enum
- Using sizeof() Operator
- How to Improve Enums With the SmartEnum Library
Nulls, Equality and Comparison
Two of the most common sources of a bug that only shows up in production.
- Differences Between != And Is Not Operators
- Nullable Types
- Null-Coalescing ?? And Null-Coalescing Assignment ??= Operators
- What Does the null! Statement Do?
- Null-Conditional Operators
- As and Is Operators
- Difference Between Is and Equality Operators in C# – "is null" vs "== null"
Operators, Conversions and Casting
Turning one type into another, safely and unsafely.
- Deep Copy of an Object
- Difference Between int.Parse() and Convert.ToInt32()
- Type Checking and Type Casting
- Early Binding and Late Binding
- Boxing and Unboxing
- Ternary Operator ? :
- Operators
- Operator Overloading
- Parse and TryParse
More Types and Objects
Everything else about types and objects in C#.
- Expression Trees
- Value vs Reference Types in C# – In Depth Guide
- Difference Between Ref and Out keywords
- Restricting a Value Lifetime With the "scoped" Keyword
- Discriminated Unions
- Unsafe Code in C# (unsafe keyword)
- ModuleInitializer Attribute
- How to Validate a GUID
- How to Build Dynamic Queries With Expression Trees
- How to Use the “Using Static” Feature
- How to Use Pointers
Where to Go Next
Where to go after the language itself:
Most arguments about OOP turn out to be arguments about inheritance. Composition covers more cases than people expect, so try it first and inherit when you genuinely have an is-a relationship.
