Question

I have the following class:

public class ChArray {
    private string m_str;
    public ChArray(string str) {
        m_str = (str.Length > m_len ? str.Substring(0, m_len) : str);
    }
    public static implicit operator ChArray(string str) {
        return new ChArray(str);
    }
}

I'm using this class as a dictionary key. Why are the following statements NOT equivalent? Using new, everything works just fine, but using a string, I get a key not found.

ChArray LINE_LEN = new ChArray("lineLen");
ChArray LINE_LEN = "lineLen"

The implicit operation returns a new ChArray, so why wouldn't this work?

Note that I'm not posting the full class to keep things simple. This DOES work if I use the new method.

Was it helpful?

Solution

The problem is not in the code you've shown here.

The problem is that, if you want to use instances of a custom class as keys in a dictionary, you need to properly overload Equals and GetHashCode.

As LordTakkera put it:

The default comparer [for a class] will check if they are actually the same object (which of course they are not).

Note that:

Object.Equals("foo", "foo");   // returns true

But

Object.Equals(new ChArray("foo"), new ChArray("foo"));   // returns false

A proper override of those two functions will provide the correct result.


This should work:

public class ChArray {
    // (as you have it)

    public override bool Equals(System.Object obj)
    {
        // If parameter cannot be cast to ChArray return false:
        ChArray p = obj as ChArray;
        if ((object)p == null)
        {
            return false;
        }

        // Return true if the fields match:
        return m_str == p.m_str;
    }

    public bool Equals(ChArrayp)
    {
        // Return true if the fields match:
        return m_str == p.m_str;
    }

    public override int GetHashCode()
    {
        return m_str.GetHashCode();
    }
}

OTHER TIPS

Maybe you need to override GetHashCode() and Equals() in your class ChArray ? These are used to compare keys.

Just the addition to another answers. I mean, the question Using new, everything works just fine, but using a string, I get a key not found. still unanswered.

When you use

var key = new ChArray("lineLen");

dictionary.Add(key, someValue);
var value = dictionary[key];

the key still the same object and because you haven't overridden the Equals method the object.Equals used which is reference comparison.

When you use

ChArray key = "lineLen";

dictionary.Add(key, someValue);
var value = dictionary[key];

it is still must work.

but you will get KeyNotFoundException if you will use

ChArray key = "lineLen";

dictionary.Add(key, someValue);
var value = dictionary["lineLen"];

or

ChArray key = "lineLen";

dictionary.Add(key, someValue);
ChArray key1 = "lineLen";
var value = dictionary[key1];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top