none
structs as hastable keys?

    Question

  • In my c# app I'm using a struct as a hashtable key. In this case the struct has only one field, of string type. I add an instance of the struct, foo, with string value "abcd" to the hashtable. Later I encounter another instance, bar, of the struct with string content "abcd". I would expect that a call to ContainsKey(bar) would answer, true, but it responds false. Am I missing something fundamental here?

    Note that I did NOT override any of the struct methods (Equals, GetHashCode, etc.) as I did not think that was necessary.

    Thanks in advance,
     Bill

    Bill Cohagan
    Tuesday, May 12, 2009 1:25 AM

Answers

  • Hans, Steve
      Found it! When the key was added the string was "Time of Use Schedule". The second instance was "Time Of Use Schedule". While close, these aren't the same. ( "of" != "Of" ).

      Thanks for the help. At least I determined that I'm stupid, not crazy!

    Bill

    Bill Cohagan
    • Marked as answer by Zhi-Xin Ye Tuesday, May 12, 2009 11:01 AM
    Tuesday, May 12, 2009 3:07 AM

All replies

  • Modify this sample so it reproduces your problem:

    using System;
    using System.Collections.Generic;

    class Program {
      static void Main(string[] args) {
        Dictionary<Test, int> dict = new Dictionary<Test, int>();
        dict.Add(new Test("abcd"), 1);
        Test t2 = new Test("abcd");
        Console.WriteLine(dict.ContainsKey(t2));
        Console.ReadLine();
      }
      struct Test {
        public string member1;
        public Test(string init) { member1 = init; }
      }
    }

    Output: True

    Hans Passant.
    Tuesday, May 12, 2009 1:35 AM
    Moderator
  • Understand that with a Hashtable, you're boxing each key into a separate object; it's not a generic container. They are then compared using reference equality (as boxed objects), and each of them will be distinct because they each get boxed into a different object.

    Recommended reading: CLR via C#, by Jeffrey Richter.

              -Steve

    Programming blog: http://nitoprograms.blogspot.com/
    I will be in Chicago for the WPF training: http://blogs.msdn.com/jaimer/archive/2009/04/01/announcing-the-using-wpf-to-build-lob-applications-training-tour.aspx
    Tuesday, May 12, 2009 1:43 AM
  • Modify this sample so it reproduces your problem:

    using System;
    using System.Collections.Generic;

    class Program {
      static void Main(string[] args) {
        Dictionary<Test, int> dict = new Dictionary<Test, int>();
        dict.Add(new Test("abcd"), 1);
        Test t2 = new Test("abcd");
        Console.WriteLine(dict.ContainsKey(t2));
        Console.ReadLine();
      }
      struct Test {
        public string member1;
        public Test(string init) { member1 = init; }
      }
    }

    Output: True

    Hans Passant.

    Hans
      Good idea. I've actually already tried something similar and was unable to reproduce the behavior -- so thought there might be something subtle going on.  But, it appears that it *should* in fact work so obviously something else is going on.  Perhaps there's a bogus character in the 2nd string, causing the strings to only look the same. This has been (and continues to be) a *tough* bug!

    Thanks for the suggestion.

    Bill
    Bill Cohagan
    Tuesday, May 12, 2009 2:43 AM
  • Understand that with a Hashtable, you're boxing each key into a separate object; it's not a generic container. They are then compared using reference equality (as boxed objects), and each of them will be distinct because they each get boxed into a different object.

    Recommended reading: CLR via C#, by Jeffrey Richter.

              -Steve

    Programming blog: http://nitoprograms.blogspot.com/
    I will be in Chicago for the WPF training: http://blogs.msdn.com/jaimer/archive/2009/04/01/announcing-the-using-wpf-to-build-lob-applications-training-tour.aspx

    Actually I'm using a generic Dictionary<IKey, object> so I don't think the boxing argument applies. Thanks for the response in any case. (See my response to Hans above.) Perhaps it's my use of an interface as the key type that is causing the problem. That's what I'm checking into now.

    Bill
    Bill Cohagan
    Tuesday, May 12, 2009 2:46 AM
  • Hans, Steve
      Found it! When the key was added the string was "Time of Use Schedule". The second instance was "Time Of Use Schedule". While close, these aren't the same. ( "of" != "Of" ).

      Thanks for the help. At least I determined that I'm stupid, not crazy!

    Bill

    Bill Cohagan
    • Marked as answer by Zhi-Xin Ye Tuesday, May 12, 2009 11:01 AM
    Tuesday, May 12, 2009 3:07 AM