Value Objects

A Value Object represents a conceptually whole value with no identity. It is defined solely by its attributes or properties and is considered immutable, meaning its state cannot be changed after creation. Two Value Objects with the same attributes are considered equal, regardless of their individual identities.

Characteristics of Value Objects:

  1. Immutability: Once created, the state of a Value Object cannot be modified. Any changes to its properties result in a new Value Object instance.

  2. Equality based on attributes: Value Objects are compared based on the equality of their attributes rather than their identities.

  3. Side-effect-free: Value Objects should not have any behavior or actions associated with them. They are primarily used to hold and model data.

  4. Lightweight: Since Value Objects are immutable and do not have identities, they are typically lightweight and easy to copy.

  5. Replaceable: If two Value Objects have the same attributes, they can be replaced with each other without any impact on the domain logic.

Eiffel.Modelling.Abstractions NuGet package contains base ValueObject class. By using abstract ValueObject class you can define your value objects.

 /// <summary>
 /// Value object
 /// </summary>
 /// <typeparam name="T">The type of value object class</typeparam>
 public abstract class ValueObject<T> where T : ValueObject<T>
 {
     /// <inheritdoc/>
     public override bool Equals(object obj)
     {
         if (obj == null || GetType() != obj.GetType())
             return false;

         T other = (T)obj;
         return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
     }

     /// <inheritdoc/>
     public override int GetHashCode()
     {
         return GetEqualityComponents()
             .Aggregate(17, (current, obj) => current * 23 + (obj?.GetHashCode() ?? 0));
     }

     /// <inheritdoc/>
     protected abstract IEnumerable<object> GetEqualityComponents();
 }

Example Location value object.

public class Location : ValueObject<Location>
{
    public string City { get; }

    public string Country { get ;}

    public Location(string city, string country)
    {
        City = city;
        Country = country;
    }
}

Last updated