Assignment evaluation in C#

09/13/08

Assignment evaluation in C#

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.


Your Host: webmaster@truewill.net
Copyright © 2000-2013 by William Sorensen. All rights reserved.