Reputation: 18895
Why does C# allow for the implicit conversion of an object to an int for equality comparison, but not for an object type to object type comparison, even though an implicit operator exists?
The bool errorHere = valueOnly == valuePair;
line gives the exception at the bottom.
class Program
{
static void Main(string[] args)
{
ValueOnly valueOnly = new ValueOnly();
ValuePair valuePair = new ValuePair();
bool areEqual = valueOnly.Value == valuePair;
bool errorHere = valueOnly == valuePair;
bool butNotHere = valueOnly == (ValueOnly)valuePair;
valueOnly = valuePair; // Or Here
}
}
public class ValuePair
{
public int Value { get; set; }
public string Text { get; set; }
public static implicit operator ValueOnly(ValuePair valuePair) {
if (valuePair.Text != null || valuePair.Value != 0) {
return new ValueOnly() { Value = valuePair.Value };
}
return null;
}
public static implicit operator int(ValuePair valuePair) {
return valuePair.Value;
}
}
public class ValueOnly
{
public int Value { get; set; }
}
Here is the error:
Error Operator '==' cannot be applied to operands of type 'ValueOnly' and 'ValuePair'
Upvotes: 1
Views: 335
Reputation: 18895
To allow valueOnly == valuePair you have to add this to the ValuePair class:
public static bool operator == (ValueOnly valueOnly, ValuePair valuePair){
ValueOnly value = valuePair;
return valueOnly.Value == value.Value;
}
This uses the implicit conversion, and then performs the equality check I'm looking for...
And now that I think of it, the implicit conversion is dumb (since I haven't provided an equality operator for the ValueOnly class):
public static bool operator == (ValueOnly valueOnly, ValuePair valuePair){
return valueOnly.Value == valuePair.Value;
}
Upvotes: 0
Reputation: 437376
C# most certainly does not allow implicit conversions of objects to int
s for any purpose. I 'm not sure if you are referring to the line
bool butNotHere = valueOnly == (ValueOnly)valuePair;
as "allowing" such a conversion. If so, it does not do any such thing. It simply invokes your own conversion operator (which if I read the code correctly will return null
since the value will be a default-constructed integer) and then does a reference comparison between the two objects (which evaluates to false
as null
is not reference-equal to anything).
It also goes without saying that once you define an implicit conversion operator C# will use it whenever it is necessary. Therefore I think your question has to do more with understanding how the equality operator works based on the types of its arguments than anything else.
Update, regarding the valueOnly == valuePair
check:
The C# specification, 7.10.6 (Reference type equality operators) states:
It is a binding-time error to use the predefined reference type equality operators to compare two references that are known to be different at binding-time. For example, if the binding-time types of the operands are two class types A and B, and if neither A nor B derives from the other, then it would be impossible for the two operands to reference the same object. Thus, the operation is considered a binding-time error.
If you want to be able to compare objects of class type for equality, the best way is to implement the IEquatable<T>
interface, and override object.Equals
to be implemented in terms of IEquatable<T>.Equals
(this means that you will also have to override object.GetHashCode
) to match.
However, it's a bad idea to rely on "hidden" conversions when comparing items. If we 're talking about comparing unrelated classes, you will save yourself a lot of anguish down the road by making the comparison as prominent as possible. To that end, I would suggest the low tech
if(valuePair.Value == valueOnly.Value)
Upvotes: 1