Values are not records
In the dotnet world, when people talk about primitive obsession, they often replace the type of the value by a record of one property, leading to implementation like
public record Age(int Value);
or, if you want to add some validation
public record Age
{
public int Value { get; }
public Age(int value)
{
if (value < 0 || value > 150) throw new ArgumentException("Invalid age");
Value = value;
}
}
But that is not enough.
First of all, considering the underlying type, a readonly struct would be more appropriate but you should also implement IComparable<Age> and the associated operators, so you could write
if(time.Age > john.Age)
{
// ...
}
For Age in particular, you may also want to implement IAdditionOperators<int, int, int>, ISubtractionOperators<int, int, int>, IDecrementOperators<int> & IIncrementOperators<int> for convenience.
The only benefit of record here is the implement of Equals and GetHashCode. But, because there is only one field, the implementation is trivial.
By using a record, you do not think about what the type of the value really is.
Microsoft does not provide a lot of guidance on when to use record, class or struct but my take is that you should use records when your type is mostly a aggregate of independent properties, for instance an Address
public record Address(string Street, string City, string ZipCode, string Country);