简体   繁体   中英

C# operator== : what is standard practice (reference/value equality)?

Explanation:

  • Equals() compares the values of two objects.
  • ReferenceEquals() compares their references.

For reference types operator== by default compares references, while for value types it performs (AFAIK) the equivalent of Equals() using reflection.

So. I have a situation where I need to compare two reference types by their values. I can explicitly call Equals() or I can overload operator== to perform the desired comparison.

However, overloading operator== for value comparison kinda-sorta violates the principle of least astonishment. On the other hand explicitly calling two-object Equals looks like overkill.

What is standard practice here?


I know how to override Equals() . The question was whether it is commonly acceptable to override operator== to test for value equality on reference types or whether it is commonly accepted practice to explicitly call Equals/ReferenceEquals to explicitly specify which comparison you want.

What is standard practice?

The "standard practice" is, if you want to check two elements for equality which isn't reference equality, you need to implement IEquatable<T> , which introduces a Equals(T other) method, and override GetHashCode . That way, you control the way these two objects are compared. Usually, this includes overriding the == and != operators as well.

while for value types it performs (AFAIK) equivalent of Equals() using reflection.

Only if your value type has a member which is a reference type. If it's all value types, it will do a bit comparison of these two objects :

// if there are no GC references in this object we can avoid reflection 
// and do a fast memcmp
if (CanCompareBits(this))
    return FastEqualsCheck(thisObj, obj);

The question was whether it is commonly acceptable to override operator== to test for value equality on reference types

It really depends on what you're doing. It is encouraged to override the == operator once you override Equals because you want a consistent behavior value equality semantics. This depends on your definition of equality between two objects.

Although, If an object is mutable, then doing value comparison might result in odd scenarios where two objects are considered equal but later, one is mutated. This should definitely be analyzed on per case basis. Usually, overriding Equals should suffice.

Equals() performs value comparison of two objects.

This is not true. The default behavior of object.Equals on value types is to compare each of the fields using their definition of equality, the default behavior of reference types is to compare their references. It can be overridden to do whatever you want it to do. It is exactly the same as the == operator in this regard.

The only difference between the == operator and Equals is that Equals will perform a virtual dispatch on the first (but not the second) operand, finding the implementation of the method based on the runtime type of that object. The == operator is entirely statically bound; it considers only the compile time type of both operands. Other than this difference in binding both have the same default behaviors, and both can be overridden to provide whatever implementation you want.

The standard practice is to always ensure that the behavior of Equals and operator == is the same for your type. If you override the Equals method to change the equality semantics, then you should also overload the == operator to provide *identical semantics`, and vice versa.

The question was whether it is commonly acceptable to override operator== to test for value equality

It depends on the object, if the object is immutable then you can override == operator, otherwise not. (Remember they are just guidelines) .

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

By default, the operator == tests for reference equality by determining whether two references indicate the same object. Therefore, reference types do not have to implement operator == in order to gain this functionality. When a type is immutable , that is, the data that is contained in the instance cannot be changed, overloading operator == to compare value equality instead of reference equality can be useful because, as immutable objects, they can be considered the same as long as they have the same value. It is not a good idea to override operator == in non-immutable types.

It's a good practice to give a semantic meaning to your code. So, if reference comparison is really something you should care about, use default behaviour for your classes; otherwise your application context dependent logic should be used for comparison. (with consistent behaviour of all the equality members like Equals , GetHashCode and operators)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM