tags:

views:

113

answers:

3

I thought i've seen it all but this... :)

I was working on a generic graph of type string,

Graph<string> graph = new Graph<string>();

Graph is declared with a class constraint like this:

public class Graph<T> where T : class

Next i fill up the graph with some dynamicly generated strings:

for (char t = 'A'; t < 'J'; t++)
{
    GraphPrim.Add(t.ToString());
}

So far so good, (Node is a internal class containing the original value and a list of references to other nodes (because its a graph))

Now, when i try to create relations between the different nodes, i have to look up the right node by checking its value and thats where the weirdness starts.

The following code, is a direct copy of the result found in the immidiate window after doing some tests:

Nodes.First().Value
"A"
Nodes.First().Value == "A"
false
Nodes.First().Value.ToString() == "A"
true

Am i totally missing something or shouldn't Nodes.First().Value == "A" use a string comparison method. (The JIT compiler has knowledge about the type beeing used on runtime, and with that, its supported methods, right?). It seems to me like when not explicitly specifying a string, it will do a reference check rather then a string test.

It would be great if someone could explain this to me,

Thanks in advance!

+3  A: 

== is a static method and therefore not virtual. The selection of which == method to use is done at compile-time, not run-time. Depending on the compile-time type of the object, it is probably choosing the implementation of == for objects that compares by reference.

If you use the virtual Equals methods instead, this will work as you expect.

Mark Byers
+5  A: 

If the Value property of your Nodes is object, the == operator in

Nodes.First().Value == "A"

will do a comparison by reference instead of comparing strings.

Dynami Le Savard
+7  A: 

If the types aren't fully known up front (i.e. Value is only known as T, and is not strictly known to be a string), use things like:

object.Equals(Nodes.First().Value,"A")

Of course, you could cast, but in this case you'd need a double-cast ((string)(object)) which is ugly.

If you know the two objects are the same type (i.e. two T values), then you can use:

EqualityComparer<T>.Default.Equals(x,y)

The advantage of the above is that it avoids boxing of structs and supports lifted Nullable<T> operators, and IEquatable<T> in addition to Equals.

Marc Gravell