Value Object
Tags: csharp, programming, tutorial, dotnet
Published: 2023-08-06 13:43:06

## What is a value object?

A value object is a design pattern that represents an immutable object with equality based on its state, not its identity. This means that two value objects are equal if they have the same properties and values, regardless of their references. For example, two money objects with the same amount and currency are equal, even if they are different instances.

A value object has the following characteristics:

- It is immutable, meaning that its state cannot be changed after creation
- It has no identity, meaning that it does not have a unique identifier or a reference to another object
- It is self-contained, meaning that it does not depend on external resources or services
- It is comparable, meaning that it can be compared with other value objects of the same type

## How to implement a value object base class in C#?

One way to implement a value object in C# is to create a base class that overrides the `Equals` and `GetHashCode` methods, and provides a copy constructor. The `Equals` method compares two value objects by calling `GetAtomicValues` method to compare their values. The `GetHashCode` method returns a hash code based on the values of the public properties. 

Here is an example of a value object base class in C#:

```csharp
public abstract class ValueObject : IEquatable<ValueObject>
{    
    public abstract IEnumerable<object> GetAtomicValues();

    public bool Equals(ValueObject? other)
    {
        return other is not null && ValueObjectsAreEqual(other);
    }

    public override bool Equals(object? obj)
    {
        return obj is not null && obj is ValueObject other && ValueObjectsAreEqual(other);
    }    

    public override int GetHashCode()
    {
        return GetAtomicValues().Aggregate(default(int), HashCode.Combine);
    }

    private bool ValueObjectsAreEqual(ValueObject other)
    {
        return GetAtomicValues().SequenceEqual(other.GetAtomicValues());
    }
}
```
Now, you have the option to inherit from the **ValueObject** class, like:

```csharp
public sealed class SampleValueObject : ValueObject
{
    public string PropertyOne { get; set; } = "Value1";

    public int PropertyTwo { get; set; } = 2;

    public override IEnumerable<object> GetAtomicValues()
    {
        yield return PropertyOne;
        yield return PropertyTwo;
    }
}
```

After defining the **SampleValueObject** class, you can write a sample xUnit unit test for the preceding class:

```csharp
[Fact]
public void Equals_WhenCalledWithEqualValueObjects_ReturnsTrue()
{
     // Arrange
     var valueObject1 = new SampleValueObject();
     var valueObject2 = new SampleValueObject();

     // Act
     var result = valueObject1.Equals(valueObject2);

     // Assert
     Assert.True(result);
}
```

## How to map Value Object in EF

Entity Framework Core supports value objects through the concept of owned entity types. To map a value object, you need to use the `.OwnsOne` method in the `OnModelCreating` method of your DbContext class. This method takes a lambda expression that specifies the navigation property that represents the value object.

```csharp
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<SampleEntity>()
         .OwnsOne(e => e.ValueObject);
}
```
This will create a table for **SampleEntity** with columns for the properties of **ValueObject**. The table name will be the same as the entity name, and the column names will be prefixed with the navigation property name. For example, the table will have columns called **ValueObject_PropertyOne** and **ValueObject_PropertyTwo**.

## Why use value objects in your code?

Using value objects in your code can improve the readability, maintainability and testability of your code, as well as avoid unnecessary mutations and side effects. Here are some of the benefits of using value objects:

- Readability: Value objects make your code more expressive and declarative, as they capture the meaning and behavior of the domain concepts. For example, a money value object can encapsulate the amount and currency, and provide methods for arithmetic operations and formatting.
- Maintainability: Value objects reduce the complexity and duplication of your code, as they encapsulate the logic and validation of the state. For example, a date value object can ensure that the date is valid and provide methods for comparison and manipulation.
- Testability: Value objects make your code easier to test, as they are self-contained and have no external dependencies. You can use simple equality checks to verify the state and behavior of the value objects, without relying on mocks or stubs.
- Immutability: Value objects prevent unwanted mutations and side effects, as they cannot be changed after creation. You can safely pass them around without worrying about their state being modified by other parts of the code.

## Summery
In summary, value object is a useful design pattern for representing objects that have no identity and are defined by their state. Using value objects in your code can improve the readability, maintainability and testability of your code, as well as avoid unnecessary mutations and side effects.

Please find [Nuget Package](https://www.nuget.org/packages/ValueObjectCore/1.0.0) and [GitHub repository](https://github.com/iPazooki/ValueObjectCore) links of this project here.