Thursday, September 15, 2016

C# Value vs Reference Types

A refresher for those who may have forgotten about the wild world of value versus reference type.

Assume you have an object as follows:

public class Person
{
    public string FirstName {get;set;}
    public string LastName {get;set;}
}

Now assume the following code is executed:

Person a = new Person() { FirstName = "John", LastName = "Doe"};
Person b = new Person() { FirstName = "John", LastName = "Doe"};

Asset.AreEqual(a,b);

This asset will fail.  At initial glance you might think "but the values are the same".  Yes, they are.  But that is not what is being evaluated!  Because a class is a reference type what is being asserted is that the memory location of a is the same as b.  In this case, they are not because they are two separate objects.

There are several ways to address this.  One way would be to override the Equals method on the Person object and do a field by field comparison.  Another way might be to override the ToString method which would return a value type that could be compared.

The way I prefer to do this is to create a method that uses reflection (and generics, recursion) thoroughly compare all the object's fields.  This way there is no refactoring if fields are added/removed/changed.

Value types, however, will pass this asset.  For example:

string a = "Hello!";
string b = "Hello!";

Asset.AreEqual(a.b);

In this case, we're not checking the reference but actually comparing the values.

Another interesting thing here that trips people up is if you pass an object by reference then all changes in a method will be reflected in the original object; not so in a value type.

Assume something like this:

public void ChangeName(Person aPerson)
{
    aPerson.FirstName = "Billy";
}

public void DoSomething()
{
    Person a = new Person() { FirstName = "John", LastName = "Doe"};

    ChangeName(a);

   Asset.AreEqual(a.FirstName, "Billy");
}

This will work because ChangeName received the memory reference to a and updated the name.  For a reference type, this will not work.

No comments:

Post a Comment