Kunal Mukherjee
Kunal Mukherjee

Reputation: 5853

How to check if an object has default values in C#

I have an object that I want to check whether it contains default values or not, in the below code but that doesn't cut it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           MyClass obj1 = new MyClass();
           MyClass obj2 = null;

           if(obj1 == new MyClass())
            Console.WriteLine("Initialized");

           if(Object.ReferenceEquals(obj1, new MyClass()))
              Console.WriteLine("Initialized");

        }
    }
}

public class MyClass
{
    public int Value {get; set; }

    public MyClass()
    {
        this.Value = 10;
    }
}

I have also used Object.ReferenceEquals() but that doesn't cut it as well.

This is the fiddle I am working on.

Is there a way to check whether an object contains default values, or if the object is empty?


Edit: In case of an newly initialized object with many nested properties, how to check whether they contain a default value or not?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           MyClass obj1 = new MyClass();
           MyClass obj2 = null;

           if(obj1 == new MyClass())
            Console.WriteLine("Initialized");

           if(Object.ReferenceEquals(obj1, new MyClass()))
              Console.WriteLine("Initialized");


        }
    }
}

public class MyClass
{
    public int Value {get; set; }

    public MyNestedClass MyProperty { get; set; }

    public MyClass()
    {
        this.Value = 10;
        this.MyProperty = new MyNestedClass();
    }
}

public class MyNestedClass
{
    public string SomeStringProperty { get; set; }

    public MyNestedClass()
    {
        this.SomeStringProperty = "Some string";
    }

}

Here is the fiddle in the case of nested objects.

Upvotes: 3

Views: 6019

Answers (2)

Ron Beyer
Ron Beyer

Reputation: 11273

Here is one method using JSON serialization that allows you to check if the objects are equal or not:

DotNetFiddle:

using System;
using Newtonsoft.Json;

public class Program
{
    public static void Main()
    {
        var defaultObj = new MasterObject();
        var notDefaultObject = new MasterObject();

        var defaultJson = JsonConvert.SerializeObject(defaultObj);
        var notDefaultJson = JsonConvert.SerializeObject(notDefaultObject);

        Console.WriteLine("First Test");
        if (defaultJson == notDefaultJson) 
            Console.WriteLine("Same thing");
        else
            Console.WriteLine("Not same thing");

        notDefaultObject.Sub1.SomeObject.SomeOtherValue = "Not a default Value";

        notDefaultJson = JsonConvert.SerializeObject(notDefaultObject);

        Console.WriteLine("Second Test");
        if (defaultJson == notDefaultJson) 
            Console.WriteLine("Same thing");
        else
            Console.WriteLine("Not same thing");

    }

}


public class MasterObject 
{
    public SubObject1 Sub1 { get; set; }
    public SubObject2 Sub2 { get; set; }
    public string SomeString { get; set; }

    public MasterObject()
    {
        Sub1 = new SubObject1();
        Sub2 = new SubObject2();
        SomeString = "Some Default String";
    }
}

public class SubObject1 
{
    public string SomeValue { get; set; }
    public SubObject2 SomeObject { get; set; }

    public SubObject1()
    {
        SomeObject = new SubObject2();
        SomeValue = "Some other Default String";
    }
}

public class SubObject2
{
    public string SomeOtherValue { get; set; }

    public SubObject2()
    {
        SomeOtherValue = "Some default";
    }
}

Output:

First Test

Same thing

Second Test

Not same thing

What is happening is that you serialize the default object and then you make changes to the "not default object", re-serialize and compare again. This can be slow because you are generating strings, but as long as all the sub-objects can be serialized this will be the simplest way to compare if an object is "default" (what you get from new) or has been modified.

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

You can achieve your goal by overriding Equals and GetHashCode, creating and saving an immutable "default" instance, and comparing the value to it:

public class MyClass {
    public static readonly MyClass DefaultInstance = new MyClass();
    public int Value { get; set; }
    public MyClass() {
        this.Value = 10;
    }
    public override int GetHashCode() {
        return Value.GetHashCode();
    }
    public override bool Equals(Object obj) {
        if (obj == this) return true;
        var other = obj as MyClass;
        return other?.Value == this.Value;
    }
}

Now you can check if the instance is equal to a newly created one by calling

if (MyClass.DefaultInstance.Equals(instanceToCheck)) {
    ... // All defaults
}

You can change what it means for an instance to be "default" by altering DefaultInstance object.

Note: this trick works well only with immutable MyClass. Otherwise some code could perform MyClass.DefaultInstance.Value = 20 and change the "default" object.

Upvotes: 4

Related Questions