Below you'll find a small program. The challenge is to predict the output of the program, then explain why it gave the output it did.

using System;
using System.Collections.Generic;

namespace Sample {
    class Program {
        static void Main(string[] args) {
            MyStruct a;

            a.a = 1;
            a.b = 2;

            Dictionary<MyStruct, int> dic = new Dictionary<MyStruct, int>();
            dic.Add(a, 1);

            Console.WriteLine("{0}", dic[a]);

            a.a = 3;

            Console.WriteLine("{0}", dic[a]);

            Console.ReadLine();

        }
    }

    struct MyStruct {
        public int a;
        public int b;
    }
}

Before you run off to Microsoft to report a bug, this isn't one. It's working as intended. The challenge is to explain why it is working as intended :)

It is working as expected because structs are value types not reference types.

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

namespace Sample
{
    class Program
    {
       static void Main(string[] args) {
           MyStruct a;

           a.a = 1;
           a.b = 2;

           MyStruct b = a;  // This makes a copy of all the values, not a copy of the pointer

           Console.WriteLine(a.Equals(b)); // true

           a.a = 3;

           Console.WriteLine(a.Equals(b)); // false because b didn't change since it is a full copy

           Console.ReadKey();
        }
    }

    struct MyStruct {
        public int a;
        public int b;
    }

}

My first suspicion was that at some point, the key would not be found (in the dictionary).
When the struct is placed in the dictionary, it is "new"ed and copied. Then the key is changed, so it won't be found.

It is because the key is changed and it has to do with how keys for Dictonary (and HashTable) are created. It uses System.ValueType.GetHashCode() to determine the key. By default, System.ValueType.GetHashCode basis it's value off the first value of the value type (in this case the 'a' member of the structure). Since we changed the value, GetHashCode returns a different value and the key can't be found.

This is one of the major reasons that you should code value types as immutable. There are some other 'quirks' that occur in the Equals() and '==' operations if you don't (and you have to take care of how you code Equals() and '==' if you decide to overload these methods, for value and object types).

Classes are reference types and structs are value types.

Second Console.Write line will generate an error as change in value of struct makes it different from the key added in the Dictionary changing struct to class will make remove the error.

This article has been dead for over six months. Start a new discussion instead.