Course contentsShow
← C#
Lesson 206 of 1,9082. Object-Oriented Design in C#Free lesson

Value Objects for Domain Integrity

You will create immutable objects that represent domain concepts defined by their properties, not their identity.

In this lesson, you will learn how to use Value Objects to represent data that is defined by its content rather than a unique ID, ensuring your domain logic remains robust and error-free.

The Problem with Primitive Types

Often, we represent domain concepts like "Money" or "Email Address" using primitive types like decimal or string. The problem is that these types are too generic. A decimal doesn't know about currencies, and a string doesn't know how to validate an email format. Furthermore, if you pass them around your code, you might accidentally mix up a Price with a Quantity because they are both just numbers.

Defining Value Objects

A Value Object is a small, immutable object that represents a descriptive aspect of your domain. Because they are immutable, once you create them, they cannot change. If you want to change the value, you create a new instance. Crucially, two Value Objects are considered equal if all their properties are the same, not because they share the same memory address or a unique ID.

Consider a Money object:

public record Money(decimal Amount, string Currency);

By using the record keyword in C#, you get value-based equality for free! If you have two Money objects, both with 10.00 and "USD", the == operator will return true because they represent the same "value" in your domain.

Why use them?

  1. Self-Validation: You can add logic to the constructor to ensure that a Money object can never hold a negative amount.
  2. Type Safety: You can no longer pass a Weight into a method expecting Money, because they are different types, even if both are just numbers under the hood.
  3. Immutability: Since the state cannot change after creation, you eliminate a massive class of bugs where data is modified unexpectedly by different parts of your system.

By shifting your mindset from "storing data in variables" to "creating objects that represent domain values," you make your code easier to read, safer to refactor, and much closer to the business logic it describes.

Key Takeaway: Value Objects use immutability and value-based equality to turn loose, error-prone data into self-validating, type-safe domain concepts.