I debugged a very interesting problem today. Here’s an example C# 3 console application that reproduces the bug. This is contrived; the actual case was more complex.
using System;
namespace AssignmentEvaluationTest
{
public class Test
{
public static void Main()
{
Test currentTest = new Test();
currentTest.HoldItem();
}
public string Item
{
get
{
InsureItemHolderInitialized();
return "An item";
}
}
public void HoldItem()
{
_itemHolder.HeldItem = Item; // NullReference
}
private void InsureItemHolderInitialized()
{
if (_itemHolder == null)
{
_itemHolder = new ItemHolder();
Console.WriteLine("_itemHolder initialized");
}
}
private ItemHolder _itemHolder;
internal class ItemHolder
{
public string HeldItem { get; set; }
}
}
}
This will print the initialized message, then throw a NullReferenceException at the commented line.
Apparently the runtime takes the line
_itemHolder.HeldItem = Item;
and evaluates _itemHolder first (null). It then evaluates Item, which has a side effect of setting _itemHolder. After that, it tries to dereference the cached value of _itemHolder (which remains null) to set HeldItem.
Introducing a variable to reference Item first is one easy fix; refactoring the code to simplify it is another.
Development Central is the blog of Bill Sorensen, a professional software developer. Much of this will relate to C#, .NET, and OOP in general.
Disclaimer
These postings are provided "AS IS" with no warranties and confer no rights.