C# Type Comparison: Type.Equals vs operator ==
Asked Answered
S

3

46

ReSharper suggests that the following be changed from:

Type foo = typeof( Foo );
Type bar = typeof( Bar );

if( foo.Equals( bar ) ) { ... }

To:

if( foo == bar ) { ... }

operator ==

// Summary:
//     Indicates whether two System.Type objects are equal.
//
// Parameters:
//   left:
//     The first object to compare.
//
//   right:
//     The second object to compare.
//
// Returns:
//     true if left is equal to right; otherwise, false.
public static bool operator ==( Type left, Type right );

Equals( Type o )

// Summary:
//     Determines if the underlying system type of the current System.Type is the
//     same as the underlying system type of the specified System.Type.
//
// Parameters:
//   o:
//     The System.Type whose underlying system type is to be compared with the underlying
//     system type of the current System.Type.
//
// Returns:
//     true if the underlying system type of o is the same as the underlying system
//     type of the current System.Type; otherwise, false.
public virtual bool Equals( Type o );

Question
Why would operator == be recommended over Equals( Type o ) when comparing Types?

Strapper answered 10/2, 2012 at 19:56 Comment(0)
P
50

I suggest that you read the excellent When is a Type not a Type? blog post by Brad Wilson. To summarize: a runtime type (represented by the internal type RuntimeType), managed by the CLR, is not always the same as a Type, which can be extended. Equals will check the underlying system type, whereas == will check the type itself.

A simple example:

Type type = new TypeDelegator(typeof(int));
Console.WriteLine(type.Equals(typeof(int))); // Prints True
Console.WriteLine(type == typeof(int));      // Prints False
Phrasing answered 13/2, 2012 at 10:56 Comment(0)
P
2

The reason is simple: The two are functionally equivalent in this case and the latter is more readable.

Prewar answered 10/2, 2012 at 19:58 Comment(3)
R# will typically suggest something and provide a valid reason; in this case if they are functionally equivalent, I have doubts that the suggestion is for readability, which is subjective. I wonder if there is another reason it is being suggested?Strapper
@MetroSmurf - R# often suggests things for the sake of readability (reducing nesting in if statements, for example).Prewar
That is quite probably the intended reason, but as the two are not functionally equivalent in this case, then surely this is a mistake in Resharper?Bowse
E
-2

From http://blogs.msdn.com/b/csharpfaq/archive/2004/03/29/when-should-i-use-and-when-should-i-use-equals.aspx

The Equals method is just a virtual one defined in System.Object, and overridden by whichever classes choose to do so. The == operator is an operator which can be overloaded by classes, but which usually has identity behaviour.

For reference types where == has not been overloaded, it compares whether two references refer to the same object - which is exactly what the implementation of Equals does in System.Object.

Value types do not provide an overload for == by default. However, most of the value types provided by the framework provide their own overload. The default implementation of Equals for a value type is provided by ValueType, and uses reflection to make the comparison, which makes it significantly slower than a type-specific implementation normally would be. This implementation also calls Equals on pairs of references within the two values being compared.

However, the main difference between the two types of comparison in normal use (where you're unlikely to be defining your own value types very often) is polymorphism. Operators are overloaded, not overridden, which means that unless the compiler knows to call the more specific version, it'll just call the identity version.

Empennage answered 10/2, 2012 at 20:0 Comment(1)
This answer tells us nothing about how instances of the Type class define Equals and ==. So I don't see how this is a useful answer to the question. Is this answer based on misreading the question?Betray

© 2022 - 2024 — McMap. All rights reserved.