A derives directly from Object class and neither A or Object overload == operator, so why doesn't next code cause an error:
class Program
{
static void Main(string[] args)
{
A a1 = new A();
A a2 = new A();
if (a1 == a2) ... ;
}
}
class A { }
thanx
A derives directly from Object class and neither A or Object overload == operator, so why doesn't next code cause an error?
As with your other question, you seem to have some strange belief that whether an overloaded operator exists has any bearing on whether an operator can be meaningfully chosen. It does not.
Again, to resolve this situation overload resolution first attempts to determine if there is a user-defined operator defined on either of the operands. As you note, there is not.
Overload resolution then falls back on the built-in operators. As I mentioned in your other question, the built-in operators are the equality operators on int, uint, long, ulong, bool, char, float, double, decimal, object, string, all delegate types and all enum types, plus the lifted-to-nullable versions of all the value types.
Given those operators we must now determine the applicable ones. There is no implicit conversion from "A" to any of the value types, to any of the nullable value types, to string, or to any delegate type.
The only remaining applicable candidate is object.
If overload resolution chooses the equality operator that compares two objects, additional constraints must be met. In particular, both operands must either be null or a reference type, or a type parameter not constrained to be a value type. That constraint is met. Also, if the two sides have types then the operand types must have some sort of compatibility relationship; you can't do "myString == myException" because there is no relationship between string and Exception. There is a relationship between "A" and "A", namely, they are identical.
Therefore the reference equality operator is chosen, and the == means "compare these two object expressions by reference".
I am mystified as to why you believe having a user-defined == operator has anything to do with this, either in this question or your other question. The absence of such a method does not prevent the compiler from generating whatever code it likes for this expression. Can you explain?
Because by default, the == operator compares the references (memory locations) of the objects a1 and a2. And because they're different instances of class A, the expression a1 == a2 always evaluates to false in your example.
Objects have a default implementation of the == operator that checks if they refer to the same object (reference comparison). So there's no reason for it to be an error. The operator does have a meaning.
Because Object has a default implementation comparing references.
The base's == operator is called that why its not giving any error.
By default, the operator == tests for
reference equality by determining if
two references indicate the same
object, so reference types do not need
to implement operator == in order to
gain this functionality.
From: http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx
The important bit concerning your question being:
reference types do not need to
implement operator == in order to gain
this functionality
Related
The equal operator and default value of generic type are two handy feature in C#. But we can't easily use them seamlessly. For example, I expect the following code can compile,
public static bool EqualsDefault<T>(T subject){
return subject == default(T);
}
Unfortunately, it'll fail, though there's an counter-intuitive alternative,
public static bool EqualsDefault<T>(T subject){
return object.Equals(subject, default(T));
}
So my question is why C# disallows the first code snippet?
The reason it does not work is that the built-in reference equality operator cannot be applied to value types.
Let's take step back and note that System.Object does not, in fact, define an equality operator ==. The C# language defines a built-in reference equality operator with the signature (see section 7.6.10 of the C# 5 specification):
bool operator ==(object x, object y);
However, there two rules about when it can be applied:
The predefined reference type equality operators require one of the following:
Both operands are a value of a type known to be a reference-type or the literal null. Furthermore, an explicit reference conversion (§6.2.4) exists from the type of either operand to the type of the other operand.
One operand is a value of type T where T is a type-parameter and the other operand is the literal null. Furthermore T does not have the value type constraint.
The spec then notes that this means that it is an error to apply the operator to two value types unless the type explicitly defines an equality operator. Since you have no constraints, value types are allowed and neither of the operands is null. Therefore, the built-in equality operator cannot be applied and an error is produced.
To remedy this, you could constrain T be a reference type:
public static bool EqualsDefault<T>(T subject) where T : class {
return subject == default(T);
}
However you do need to be aware that the above is always a reference comparison. The compiler will only invoke the == operator on the most specific applicable type at compile time, which in this case is object.
A better alternative is to use EqualityComparer<T>.Default to prevent boxing of value types:
public static bool EqualsDefault<T>(T subject) {
return EqualityComparer<T>.Default.Equals(subject, default(T));
}
I suppose you could ask why C# was not designed to have a default equality operator that can be applied to value types without boxing. I do not know the full reason, but I suspect that it might be more confusing than it is now to determine which methods you are calling in which situations. I think it would be undesirable if in normal methods the overloaded operator was called but in generic methods another mechanism was used. Although you can argue that can happen now with reference types.
As previously mentioned, the compiler is complaining because T could be anything: reference types or struct.
Hence if you make it explicit with constraint:
public static bool EqualsDefault<T>(T subject) where T : class{
return subject == default(T);
}
It'll not complain anymore. Because now, the compiler knows, it's always going to be reference types.
Apparently, for the second one.
public static bool EqualsDefault<T>(T subject){
return object.Equals(subject, default(T));
}
It works because, all the pre-defined or user-defined types in .net directly or indirectly inherit from object and object implements Equals method.
For my own implementation of an Equals() method, I want to check a bunch of internal fields. I do it like this:
...
_myNullableInt == obj._myNullableInt &&
_myString == obj._myString &&
...
I would assume, that this compares the values, including null, for equality not the object address (as a reference euqality compare operation would) because:
It is said so for "predefined value types" in this MSDN doc here.
I assume Nullable<int> is such a "predefined value type" because of it is in the System Namespace according to this MSDN doc.
Am I right to assume that the VALUES are compared here?
Note: Unit tests showed "Yes", but I wanted to be reassured by others with this question, just in case I missed something.
In C#, there's a concept called "Lifted Operators", described in section 7.3.7 of the language specification (Version 5 download):
Lifted operators permit predefined and user-defined operators that operate on non-nullable value types to also be used with nullable forms of those types. Lifted operators are constructed from predefined and user-defined operators that meet certain requirements, as described in the following
And specifically:
For the equality operators
== !=
a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. The lifted form is constructed by adding a single ? modifier to each operand type. The lifted operator considers two null values equal, and a null value unequal to any non-null value. If both operands are non-null, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.
So, since there's an == operator defined between ints, there's also one defined for int?s
If you compare those values it will actually call the Nullable<T>.Equals method, since both values are nullable ints.
Nullable<T>.Equals will eventually call the == compare keyword of int, if both values are not null. So in the end, it will indeed check the values.
The code from the Equals method shows this well:
public override bool Equals(object other)
{
if (!this.HasValue)
{
return (other == null);
}
if (other == null)
{
return false;
}
return this.value.Equals(other);
}
If reference type doesn't overload an equality operator ==, then build-in equality operator on Object will be used instead. Why isn't the same true for user-defined structs:
struct A{ }
static void Main(string[] args)
{
A a = new A();
A a1 = new A();
bool equal= (a == a1); //error
}
Namely, doesn't ValueType ( from which all structs derive ) also overload == operator?
How would such a default == operator work? For reference types, comparing adresses is reasonable, but since that check will never be true for two ValueTypes (since if two ValueTypes are in scope then they are guaranteed to have different locations on the stack,) address comparison is pointless.
As the compiler has helpfully pointed out, ValueType very intentionally does not have a default == operator.
Structs probably don't provide a default == operator implementation because, unlike a class instance, a struct has no concept of reference-style identity.
From the guidelines:
Implementing the Equality Operator
(==) on Value Types
In most programming languages there is
no default implementation of the
equality operator (==) for value
types. Therefore, you should overload
== any time equality is meaningful.
You should consider implementing the
Equals method on value types because
the default implementation on
System.ValueType will not perform as
well as your custom implementation.
Implement == any time you override the
Equals method.
However, structs do provide a default Equals Method implementation which will do a memberwise compare using reflection.
I'm tryign to get my head around the use of System.Object.operator==().
My Effective C# book, and the page here (http://www.srtsolutions.com/just-what-is-the-default-equals-behavior-in-c-how-does-it-relate-to-gethashcode), says that:
"System.Object.operator==() will call a.Equals(b) to determine if a and b are equal".
So with my code:
object a = 1;
object b = 1;
if(object.Equals(a, b))
{
// Will get here because it calls Int32.Equals(). I understand this.
}
if(a == b)
{
// I expected it to get here, but it doesn't.
}
I expected (a == b) to call Int32's overriden Equals and compare values in the same way that static objet.Equals() does. What am I missing?
Edit: I should perhaps have added that I can see what (a == b) is testing - it's testing reference equality. I was thrown by the book which seems to suggest it will work internally much as static object.Equals(obect, object) will.
I'm not sure why the book would say that; it is emphatically untrue that the default == calls Equals. Additionally, object does NOT overload ==. The operator == by default performs a value-equality comparison for value types and a reference-equality comparison for reference types. Again, it is NOT overloaded for object (it is for string). Therefore, when you compare object a = 1 and object b = 1 using the == operator you are doing a reference-equality comparison. As these are different instances of a boxed int, they will compare differently.
For all that are confused by this issue, I encourage you to read §7.10 and especially §7.10.6 of the specification extremely carefully.
For more on the subtleties of boxing (or why we need it in the first place), I refer you to a previous post on this subject.
As the object type doesn't override == and == checks for reference equality by default, the references of a and b are compared, as both are objects. If you want to compare value equality, you have to unbox the ints first.
When two objects are tested for equality they are tested to see if they are referencing the same object. (EDIT: this is generally true, however == could be overloaded to provide the functionality that you receive from a.equals)
So
object a = 1;
object b = 1;
These do not point to the same address space.
However if you did
object a = 1;
object b = a;
Then these would point to the same address.
For a real life example, take two different apartments in the same building, they have the exact same layout, same 1 bedroom, same kitchen, same paint everything about them is the same, except that apartment a is #101 and apartment b is #102. In one sense they are the same a.equals(b), but in another sense they are completely different a != b.
== implementation of object checks for identity, not equality. You have two variables that point to two different objects that's why == returns false.
You declared a and b as object which is a reference type and not a value type. So with a==b you are comparing references of objects (which will be different) rather than the values.
System.Object.operator==() will call a.Equals(b) to determine if a and b are equal
This is simply not true. If that were the case then you'd have a == b returning true, since a.Equals(b) returns true. Equals is a virtual method, so it doesn't matter that int values are boxed; if you call a.Equals, that compiles to a callvirt and the vtable is used.
So the static == operator does not use a.Equals(b) internally. It tests for reference equality by default. It only does otherwise if the static == operator has been overloaded for the types in the expression as they are declared at compile time.
System.Object does not overload ==, so a == b just tests for reference equality (and returns false). Since operator overloading is implemented as a static method, it's not virtual.
Object.Equals, on the other side, is specified as follows:
The default implementation of Equals supports reference equality for reference types, and bitwise equality for value types. Reference equality means the object references that are compared refer to the same object. Bitwise equality means the objects that are compared have the same binary representation.
Since a and b have the same binary representation, Object.Equals(a, b) returns true.
In Java there are "==" and "equals" operator for reference types and "==" for value types. for reference type, "==" means both objects point to the same location and "equals" means their values are the same. does C# has similar operators for value type and reference types?
Well, == can be overloaded for reference types. For example:
string a = new string('x', 10);
string b = new string('x', 10);
Console.WriteLine(a == b); // True
Console.WriteLine(Object.ReferenceEquals(a, b)); // False
Unless it's overloaded, == means "reference equality" aka "object identity" for reference types. (As Marc says, you may override Equals without overloading ==.)
For value types, you have to overload == otherwise the C# compiler won't let you use it for comparisons. .NET itself will provide an implementation of Equals which usually does the right thing, but sometimes slowly - in most cases, if you write your own custom value type you'll want to implement IEquatable<T> and override Equals as well - and quite possibly overload various operators.
C# allows the == operator to be overloaded (and the Equals method to be overridden - although == and Equals don't have to mean the same thing).
If you want to mean "the same instance", then object.ReferenceEquals (for reference-types) is the best option. Value types default to internal equality.
Straight out of MSDN:
For predefined value types, the
equality operator (==) returns true if
the values of its operands are equal,
false otherwise. For reference types
other than string, == returns true if
its two operands refer to the same
object. For the string type, ==
compares the values of the strings.
Jon Skeet should be able to give you a perfect answer though :P
When should I use == and when should I use Equals?
http://blogs.msdn.com/csharpfaq/archive/2004/03/29/102224.aspx
This is precisely the way it works with .NET as well. The C# FAQ blog explains equals better:
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.