1

I am trying to understand the use case for ValueObject in C#, when to use and what's the need for ValueObject. I see in the documentation that it can be used when we want to initialize object and then don't want to change the properties that mean making it immutable, but is it not same with Singleton pattern where you can initialize object properties in constructor and it will persist for the lifetime of the application ? Now why we need ValueObject and what is all with this EqualityComparer and hashCode() etc.

Code from Microsoft Docs:

    public abstract class ValueObject
    {
        protected static bool EqualOperator(ValueObject left, ValueObject right)
        {
            if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null))
            {
                return false;
            }
            return ReferenceEquals(left, null) || left.Equals(right);
        }
    
        protected static bool NotEqualOperator(ValueObject left, ValueObject right)
        {
            return !(EqualOperator(left, right));
        }
    
        protected abstract IEnumerable<object> GetEqualityComponents();
    
        public override bool Equals(object obj)
        {
            if (obj == null || obj.GetType() != GetType())
            {
                return false;
            }
    
            var other = (ValueObject)obj;
    
            return this.GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
        }
    
        public override int GetHashCode()
        {
            return GetEqualityComponents()
                .Select(x => x != null ? x.GetHashCode() : 0)
                .Aggregate((x, y) => x ^ y);
        }
        // Other utility methods
    }

Now Address entity:

    public class Address : ValueObject
    {
        public String Street { get; private set; }
        public String City { get; private set; }
        public String State { get; private set; }
        public String Country { get; private set; }
        public String ZipCode { get; private set; }
    
        public Address() { }
    
        public Address(string street, string city, string state, string country, string zipcode)
        {
            Street = street;
            City = city;
            State = state;
            Country = country;
            ZipCode = zipcode;
        }
    
        protected override IEnumerable<object> GetEqualityComponents()
        {
            // Using a yield return statement to return each element one at a time
            yield return Street;
            yield return City;
            yield return State;
            yield return Country;
            yield return ZipCode;
        }
    }

In above code what is this address and why did we use ValueObject and what is all this equalOperator and all written in ValueObject class, just trying to understand the use case of using ValueObject in real time and why do we need it and it's real time use case on what scenarios to use ValueObjects, and why do we need Equality operator, not equal operator inside valueObject.

I am novice on this topic.

halfer
  • 19,824
  • 17
  • 99
  • 186
VR1256
  • 1,266
  • 4
  • 28
  • 56
  • This "ValueObject" is not part of C# itself, nor required by any means. Having worked in code with a similar base type (albeit one that used reflection), I can confidentially say from an intersection of _experience and opinion, without any individual points_: **"Don't Do It"**. Use code generation provided by tooling (ReSharper, recent VS?) or generation using TT or similar. – user2864740 Sep 11 '20 at 20:26
  • Include a link to the documentation / source of the code, as such might also provide it's own rationale. – user2864740 Sep 11 '20 at 20:27
  • As far as a "why", as envisioned by some Original Authors: *it reduces code duplication, at the expensive of introducing an artificial sub-type relation, as concrete types only need to provide the values of members*, as done via GetEqualityComponents. This itself is a non-issue when using tooling with automatic code generation / updating. – user2864740 Sep 11 '20 at 20:30
  • There is _no singleton "pattern"_ here, and it has the same _immutability_ "requirements" or "issues" as any type involved in GetHashCode. Putting a mutable type in a Dictionary, any then changing the value such as the subsequent GetHashCode value is different will make break it's usage in Dictionary. It doesn't matter if the GetHashCode value is computed in the concrete type or some base type - _if the GetHashCode value changes, there is a potential for abuse / incorrect semantics in a context which requires a stable GetHashCode_. I recommend all types be made immutable, as feasible. – user2864740 Sep 11 '20 at 20:33
  • 2
    @VijenderReddyChintalapudi I think this person has a good write up on the `Value Object` and gives a small idea of a real world example of use. - (https://enterprisecraftsmanship.com/posts/value-objects-explained/) – Ryan Wilson Sep 11 '20 at 20:39
  • That article confuses “Value Objects” with a `ValueObject` base type. _No_ such bass type is required to achieve the claimed benefits. All the same benefits can be achieved with _normal immutable types_ ‘without an identity’. Extending a type does not add any guarantees or implicit mutability. – user2864740 Sep 14 '20 at 02:58
  • @user2864740 can you answer in what scenarios it is useful and where to use in real time, I understand concept behind it and how to use it, I just don't understand where we can apply it thanks – VR1256 Sep 14 '20 at 13:33
  • 1
    Can't you just use `record`s for immutability? – AgentFire Aug 15 '21 at 14:10

1 Answers1

2

ValueObject is not the same as value objects or immutable objects. imho that ValueObject class should be used for business logic when you use a Domain Driven Design similar approach.

In DDD, value objects cannot be identified by an Id, but by the fields in the object, thus the need for equality operators that compares one or more properties in the object.

That's also the reason why you cannot change the properties, since the object would then not be comparable to other loaded instances of it. Like in the example, if you change the street number, it's not the same address anymore.

When implementing DDD value objects you would have to copy all that comparison logic into every class and therefore duplicate code.

The ValueObject class removes the need of that and makes your own objects more business centric (i.e. more readable), as it should when using DDD (or just a clean business layer for that matter).

jgauffin
  • 99,844
  • 45
  • 235
  • 372