Vadim's Weblog

Never stop learning.

Archive for the ‘Reference Type’ Category

Comparing Reference Types in Unit Tests.

Posted by Vadim on July 3, 2008

If you’ve done some unit testing, you’re familiar with Assert.AreEqual method.  Have you try to compare two objects that have the same value(s) but the AreEqual method tells you that they are not equal?  For example let assume that we have a class Point:

   1: private class Point
   2: {
   3:   private int _x;
   4:   private int _y;
   5:  
   6:   public Point(int x, int y)
   7:   {
   8:     _x = x;
   9:     _y = y;
  10:   }
  11: }

And we test for the constructor:

   1: [Test]
   2: public void Point_constructor_test()
   3: {
   4:   Point point = new Point(2, 3);
   5:   Assert.AreEqual(point, new Point(2, 3));
   6: }

When I run this test using MbUnit, the assertion fails.  The reason it fails because Point is a reference type.     Actually what is getting compared is objects references (not objects values) and of course they have different references.

One way we could fix it is to make Point a Value Type by replacing class with struct.

   1: private struct Point
   2: {
   3:   private int _x;
   4:   private int _y;
   5:   
   6:   public Point(int x, int y)
   7:   {
   8:     _x = x;
   9:     _y = y;
  10:   }
  11: }

This definitely resolves the issue.

Another thing we could do is implement IEquatable<T> interface:

   1: private class Point : IEquatable<Point>
   2: {
   3:   private int _x;
   4:   private int _y;
   5:  
   6:   public Point(int x, int y)
   7:   {
   8:     _x = x;
   9:     _y = y;
  10:   }
  11:  
  12:   public bool Equals(Point other)
  13:   {
  14:     return (_x == other._x) && (_y == other._y);
  15:   }
  16: }

[Updated] However, MbUnit test still will fail because deep inside MbUnit’s AreEqual calls object.Equal(object).  In order for AreEqual to succeed in this case, it needs to call generic version of AreEqual.  Something like this:

   1: private static bool AreEqual<T>(T expected, T actual)
   2: {
   3:   if (expected is IEquatable<T> )
   4:     return ((IEquatable<T>)expected).Equals(actual);
   5:   return expected.Equals(actual);
   6: }

It means we need to modify our test little bit. Instead of AreEquals method we can use IsTrue one.

   1: [Test]
   2: public void Point_constructor_test()
   3: {
   4:   Point point = new Point(2, 3);
   5:   Assert.IsTrue(point.Equals(new Point(2, 3)));
   6: }

In software development the same problem can be solved many different ways.  I assume that most common solution is going to be comparing some public properties in the object instead of the whole object.

Let assume assume that our Point class has public properties X and Y.  Here’s an example how my test would look:

   1: [Test]
   2: public void Point_constructor_test()
   3: {
   4:   Point point1 = new Point(2, 3);
   5:   Point point2 = new Point(2, 3);
   6:   Assert.AreEqual(point1.X, point2.X);
   7:   Assert.AreEqual(point1.Y, point2.Y);
   8: }

kick it on DotNetKicks.com

Posted in .Net, C#, MbUnit, Reference Type, TDD | 3 Comments »

Reference Type interview questions.

Posted by Vadim on June 30, 2008

Part of my job is to interview developers for open position at my company.  I’m surprised how many times people give wrong answers to questions related to Reference type vs. Value type.  Bellow list of the questions some interviewers get incorrectly:

Question 1: Describe behavior of the code bellow:

   1: static void Main(string[] args)
   2: {
   3:   StringBuilder builder = null;
   4:   Foo(builder);
   5:   Console.WriteLine(builder.ToString());
   6: }
   7:  
   8: private static void Foo(StringBuilder builder)
   9: {
  10:   builder = new StringBuilder("Interview");
  11: }

Incorrect Answer 1: It will output “Interview”.

Correct Answer 1: NullReferenceException will be thrown on line 6.  Because builder is null and cannot access ToString() method.

Question 2: What will the output of the code bellow?

   1: static void Main(string[] args)
   2: {
   3:   StringBuilder builder = null;
   4:   Console.WriteLine(Foo(builder));
   5: }
   6:  
   7: private static bool Foo(StringBuilder builder)
   8: {
   9:   return builder is StringBuilder;
  10: }

Incorrect Answer 2: True

Correct Answer 2: False

Often people are very eager to demonstrate their knowledge of the subject and they volunteer statements like this one:

Reference Types live on the heap and Value Types on the stack.

And this triggers a question like this one from me:

   1: class A
   2: {
   3:   B b = new B();
   4:  
   5:   class B
   6:   {
   7:     public int i;
   8:   }
   9: }

Does it mean that in the code above b of type B will be stored on the heap but b‘s member i of type int is going to be stored on the stack?

This questions really confuses some people.

Correct statement is:

Reference Types and instance Value Types live on the heap and local Value Types live on the stack.

The purpose of this post is not to make fun but to educate.

kick it on DotNetKicks.com

Posted in .Net, C#, Reference Type | 3 Comments »