Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this expected C# 4.0 Tuple equality behavior?

I'm seeing different behavior between using .Equals and == between two of .NET 4.0's new Tuple<> instances. If I have overridden Equals on the object in the Tuple<> and call .Equals on the Tuples the override of Equals will be called. If I use == on the Tuples the override of Equals is not called. Is that by design and does it make sense?

EDIT: From answers and comments I can tell I'm not being clear. I know Tuple<> is a reference type and that for reference types == will check identity (ReferenceEquals). But, should Tuple<> override == to check equality of the objects it contains? For consistency, probably not.

For example if I have a simple object

public class NameAndNumber
{
    public int Number { get; set; }
    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        if (obj is NameAndNumber)
        {
            NameAndNumber other = (NameAndNumber)obj;
            return Number == other.Number && Name == other.Name;
        }

        return false;
    }
}

and then I do something like this:

Tuple<NameAndNumber, NameAndNumber> left = new Tuple<NameAndNumber, NameAndNumber>(
      new NameAndNumber { Name = "one", Number = 1 }, 
      new NameAndNumber { Name = "two", Number = 2 });
Tuple<NameAndNumber, NameAndNumber> right = new Tuple<NameAndNumber, NameAndNumber>(
      new NameAndNumber { Name = "one", Number = 1 }, 
      new NameAndNumber { Name = "two", Number = 2 });
bool operatorResult = left == right;
bool equalsResult = left.Equals(right);
Console.Out.WriteLine("operatorResult = {0}  equalsResult = {1}", 
        operatorResult, equalsResult);

I get operatorResult = false equalsResult = true

Should I be expecting that?

I know the implementation of Equals on NameAndNumber isn't "right" it's just simplified sample code.

I have also tried implementing IEquatable, ==, !=, and GetHashCode. Same results.

like image 706
Mike Two Avatar asked Sep 27 '09 07:09

Mike Two


People also ask

What is an expected expression in C?

Expected expression. This error is produced whenever the compiler is expecting an expression on the line where the error occurred. In the following example, the trailing comma in the initializer indicates to the compiler that another expression will follow.

What does expected ')' before ';' token mean?

It literally means what it's saying. You're missing an important parenthesis there, bud. Check your code before you hit the semicolon.

What is token error in C?

Error: expected ')' before ';' token in C The error: expected ')' before ';' token may occur by terminating the statements which should not be terminated by the semicolon. Consider the given example, here I terminated the #define statement by the semicolon, which should not be terminated.

What is the meaning of error expected?

expected” This error occurs when something is missing from the code. Often this is created by a missing semicolon or closing parenthesis.


4 Answers

The results you see come from a design compromise, Tuples are now shared between F# and C#. The main point is that all Tuples are indeed implemented as reference types, that was not so obvious.

The decision whether Tuples should do deep or shallow equality checks was moved to two interfaces: IStructuralComparable, IStructuralEquatable. Note that those 2 are now also implemented by the Array class.

like image 134
Henk Holterman Avatar answered Sep 28 '22 15:09

Henk Holterman


For Reference Type: == performs an identity comparison, i.e. it will only return true if both references point to the same object. While Equals() method is expected to perform a value comparison, i.e. it will return true if the references point to objects that are equivalent.

For reference types where == has NOT been overloaded, it compares whether two references refer to the same object

like image 28
J.W. Avatar answered Sep 28 '22 14:09

J.W.


By default, the operator == tests for reference equality, so Yes the result you are seeing is expected.

See Guidelines for Overriding Equals() and Operator == (C# Programming Guide):

In C#, there are two different kinds of equality: reference equality (also known as identity) and value equality. Value equality is the generally understood meaning of equality: it means that two objects contain the same values. For example, two integers with the value of 2 have value equality. Reference equality means that there are not two objects to compare.

like image 41
Mitch Wheat Avatar answered Sep 28 '22 16:09

Mitch Wheat


By default, == (on a class) means reference equality; i.e. are they the same instance; what object.ReferenceEquals(x,y) would return.

You can provide your own == / != operators to get the expected behaviour - and when you override Equals it is important to override GetHashCode too (otherwise you break usage as a key - Why is it important to override GetHashCode when Equals method is overriden in C#?):

public static bool operator == (NameAndNumber x, NameAndNumber y) {
    if (x == null && y == null) return true;
    if (x == null || y == null) return false;
    return x.Number == y.Number && x.Name == y.Name;
    // or if polymorphism is important: return x.Equals(y);
}
public static bool operator !=(NameAndNumber x, NameAndNumber y) {
    return !(x == y); // lazy but works
}
public override int GetHashCode() {
    return (Name == null ? 0 : Name.GetHashCode()) +
        17 * Number.GetHashCode();
}
like image 42
Marc Gravell Avatar answered Sep 28 '22 15:09

Marc Gravell