707

I have a condition in a silverlight application that compares 2 strings, for some reason when I use == it returns false while .Equals() returns true.

Here is the code:

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
    // Execute code
}

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
    // Execute code
}

Any reason as to why this is happening?

poke
  • 369,085
  • 72
  • 557
  • 602
Drahcir
  • 12,311
  • 19
  • 63
  • 76
  • 4
    See also: http://stackoverflow.com/questions/144530/or-equals – Arrow Jun 07 '12 at 08:39
  • 18
    String overrides `==`, but operators are not polymorphic. In this code, the `==` operator is invoked on type `object`, which does an identity comparison instead of a value one. – Drew Noakes Aug 26 '14 at 16:38
  • 25
    To expand on @DrewNoakes' comment: The compiler chooses an `==` overload based on the compile-time type of the operands. The `Content` property is `object`. Operators are not virtual, so the default implementation of `==` is called, giving a reference equality comparison. With Equals, the call goes to the virtual method `object.Equals(object)`; `string` overrides this method and performs an ordinal comparison on the string content. See http://msdn.microsoft.com/en-us/library/fkfd9eh8(v=vs.110).aspx and http://referencesource.microsoft.com/#mscorlib/system/string.cs,507. – phoog Jan 08 '15 at 17:56
  • 8
    @phoog's explanation is precise. It should be noted that when the left-hand side of `==` has compile-time type `object` and the right-hand side has compile-time type `string`, then the C# compiler must pick the (problematic, in this case) overload `operator ==(object, object)`; but it ___will___ issue a compile-time warning that it could be unintended. So _read_ the compile-time warnings! To fix the issue and still use `==`, cast the left-hand side to `string`. If I remember correctly, the warning text suggests just that. – Jeppe Stig Nielsen Oct 08 '17 at 15:03
  • 2
    @JeppeStigNielsen +1 for the advice to read compiler warnings. Even better: turn on the warnings-as-errors option to force everyone to pay attention to them. – phoog Oct 08 '17 at 17:17
  • this is due to value equality (equal method) and referential equality(== operator), as the equal method checks the values while the same == is checked the reference. – SiwachGaurav Jul 09 '21 at 12:44

20 Answers20

526

When == is used on an expression of type object, it'll resolve to System.Object.ReferenceEquals.

Equals is just a virtual method and behaves as such, so the overridden version will be used (which, for string type compares the contents).

poke
  • 369,085
  • 72
  • 557
  • 602
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • 67
    Unless the operator is specifically implemented in the class – Dominic Cronin Nov 19 '11 at 21:11
  • 38
    @DominicCronin This isn't true. Even if == is implemented in the class it will be ignored because the type on the left of the comparison is object. It looks like operator overloads are determined at compile time and at compile time all it knows is that the left hand side is an object. – MikeKulls Jul 15 '12 at 22:53
  • @MikeKulls In the question, the type returned by .Content is object, so yes. However, Mehrdad says "an object type", not "a reference of type object". My interpretation was that he meant a reference type, and that the implementation of == would resolve to that on object. Even so, operator overloads are resolved in a similar manner to that for virtual methods. – Dominic Cronin Jul 16 '12 at 12:36
  • 4
    @DominicCronin I believe your first statement is correct in that == will resolve to object but your second statement that operator overloads resolve in a similar manner is not. They are quite different which is why .Equals will resolve to string while == will resolve to object. – MikeKulls Jul 16 '12 at 21:37
  • 9
    To be clear,`object` type (notice the monospace font) is technically meant to be "an expression of type `System.Object`". It does not have anything to do with the runtime type of the instance that is referred to by the expression. I think the statement "user-defined operators are treated like `virtual` methods" is extremely misleading. They are treated like overloaded methods and only depend on the compile-time type of the operands. In fact, after the set of candidate user-defined operators is computed, the rest of the binding procedure will be exactly the method overload resolution algorithm – Mehrdad Afshari Jul 16 '12 at 22:28
  • @MehrdadAfshari Perhaps I should have said that operator overloads are resolved in a manner similar to that for other overloads. Perhaps the way I put it was inexact terminology, but not "extremely misleading" in this context. @MikeKulls I've just written the code to test this, and I can confirm that if you implement an operator overload, it will be used. Yes - of course the signature must match, which in this case means that you need to code `public static operator ==(object a, Foo b){...}` or whatever, but overloading operators remains essentially very similar to overloading methods. – Dominic Cronin Jul 17 '12 at 12:40
  • 4
    @DominicCronin The misleading part is that `virtual` method resolution depend on the actual runtime type of an instance, whereas that is _completely_ ignored in operator overload resolution, and that is indeed the whole point of my answer. – Mehrdad Afshari Jul 17 '12 at 17:22
  • 1
    So why does `string a = String.Copy("xyz"), b = String.Copy("xyz"); Console.WriteLine(String.ReferenceEquals(a,b)); Console.WriteLine(a==b);` print `false` then `true`. Seems `==` is like `Equals` for `string`? – xagyg Mar 25 '13 at 23:30
  • 2
    @xagyg It is "overloaded" for the `string` type. Try: `Console.WriteLine((object)a == (object)b)` where `a` and `b` are strings and the result will be the same as `ReferenceEquals`. Similarly, if you had declared an overloaded `==` operator in your own type, you could mimic the same behavior of `string`. – Mehrdad Afshari Mar 26 '13 at 00:58
  • 1
    This answer could be made clearer by pointing out that ListItem.Content is of type object, so == resolves to ==(object, object) rather than ==(string, string). – Dave Mackersie Dec 18 '17 at 18:10
431

When comparing an object reference to a string (even if the object reference refers to a string), the special behavior of the == operator specific to the string class is ignored.

Normally (when not dealing with strings, that is), Equals compares values, while == compares object references. If two objects you are comparing are referring to the same exact instance of an object, then both will return true, but if one has the same content and came from a different source (is a separate instance with the same data), only Equals will return true. However, as noted in the comments, string is a special case because it overrides the == operator so that when dealing purely with string references (and not object references), only the values are compared even if they are separate instances. The following code illustrates the subtle differences in behaviors:

string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;  // Notice: set to object variable!

Console.WriteLine($"{object.ReferenceEquals(s1, s2)} {s1 == s2} {s1.Equals(s2)}");
Console.WriteLine($"{object.ReferenceEquals(s1, s3)} {s1 == s3} {s1.Equals(s3)}");
Console.WriteLine($"{object.ReferenceEquals(s1, s4)} {s1 == s4} {s1.Equals(s4)}");

The output is:

True True True     // s1, s2
False True True    // s1, s3
False False True   // s1, s4

Summary:

Variables .ReferenceEquals == .Equals
s1, s2 True True True
s1, s3 False True True
s1, s4 False False True
BenKoshy
  • 33,477
  • 14
  • 111
  • 80
BlueMonkMN
  • 25,079
  • 9
  • 80
  • 146
  • 11
    Spot on. The '==' operator compares object references (shallow comparison) whereas .Equals() compares object content (deep comparison). As @mehrdad said, .Equals() is overridden to provide that deep content comparison. – Andrew May 02 '09 at 13:43
  • 2
    I will leave the post here because I think it's valuable to emphasize what's *not* happening since you have to be paying close attention to realize it. (And I think the code to demonstrate the correct and incorrect understandings is worthwhile too.) I hope the rating won't go below 0. – BlueMonkMN May 02 '09 at 14:39
  • 11
    Surely String implements a custom == operator. If it didn't then using == would not compare the content. So String is a bad example to use here, as it doesn't help us understand the general case where no custom operator has been defined. – Dominic Cronin Nov 19 '11 at 21:07
  • 13
    +1 for the epic code example, that made me make sense of this. Shows the general case of the static type(Left Hand Side type) being object and the specific case of of the static type(/RHS type) being string. And touches well on string interning. – barlop Apr 22 '14 at 12:55
  • I think it would be better to put what it does first, then explain (rewrite) what it does not do. As it is now, it is easy for a skimmer to read the incorrect answer as correct. – Trisped Jan 27 '16 at 21:09
  • 3
    Ok, but i still don't understand why object.ReferenceEquals(s1, s2) returns true. How does it work? In memory they are different objects so why does reference comparison returns true? Even when one replaces references with: string s1 = "test"; string s2 = "tes" + "t"; – badsamaritan Jul 03 '16 at 11:08
  • 10
    When multiple string literals are identical, the compiler is smart enough to use the same address for both references because strings in .NET are immutable. – BlueMonkMN Jul 03 '16 at 14:32
  • 5
    @badsamaritan Because of string interning – Alexander Derck Jan 31 '17 at 22:57
  • Why does this answer have 12 down-votes though? Double-digit down-votes always gives me pause even for highly-up-voted answers. – rory.ap Oct 02 '19 at 14:43
  • 3
    @rory.ap If you look at the edit history of this answer, it was worded in a less appealing way for quite a while starting out with an inaccurate explanation (even though it was labeled as inaccurate, that might not be the best way to start). That might have confused a number of people. – BlueMonkMN Oct 05 '19 at 00:57
58

== and .Equals are both dependent upon the behavior defined in the actual type and the actual type at the call site. Both are just methods / operators which can be overridden on any type and given any behavior the author so desires. In my experience, I find it's common for people to implement .Equals on an object but neglect to implement operator ==. This means that .Equals will actually measure the equality of the values while == will measure whether or not they are the same reference.

When I'm working with a new type whose definition is in flux or writing generic algorithms, I find the best practice is the following

  • If I want to compare references in C#, I use Object.ReferenceEquals directly (not needed in the generic case)
  • If I want to compare values I use EqualityComparer<T>.Default

In some cases when I feel the usage of == is ambiguous I will explicitly use Object.Reference equals in the code to remove the ambiguity.

Eric Lippert recently did a blog post on the subject of why there are 2 methods of equality in the CLR. It's worth the read

Amen Jlili
  • 1,884
  • 4
  • 28
  • 51
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • Well Jared, you directly violate Jeff's famous “The best code is no code at all here.” Is this really justified? On the other hand, I can see where this stems from and why it might be desirable to make the semantics explicit. For this case, I very much prefer VB’s way of dealing with object equality. It's short *and* unambiguous. – Konrad Rudolph May 02 '09 at 13:51
  • @Konrad, I really should have said "when I'm unfamiliar with a type, i find the best practice is the following". Yes VB has much better semantics here because it truly separates value and reference equality. C# mixes the two together and it occasionally causes ambiguity errors. – JaredPar May 02 '09 at 14:04
  • 13
    This is not entirely true. == cannot be overridden, it is a static method. It can only be overloaded, which is an important difference. So the code that is executed for a == operator is linked at compile time, while Equals is virtual and found at execution time. – Stefan Steinegger Aug 15 '13 at 06:54
  • Here is an actual link (for now) to the mentioned article: https://learn.microsoft.com/en-us/archive/blogs/ericlippert/double-your-dispatch-double-your-fun – user1234567 Jun 18 '20 at 13:01
44

== Operator

  1. If operands are Value Types and their values are equal, it returns true else false.
  2. If operands are Reference Types with exception of string and both refer to the same instance (same object), it returns true else false.
  3. If operands are string type and their values are equal, it returns true else false.

.Equals

  1. If operands are Reference Types, it performs Reference Equality that is if both refer to the same instance (same object), it returns true else false.
  2. If Operands are Value Types then unlike == operator it checks for their type first and if their types are same it performs == operator else it returns false.
Robert Synoradzki
  • 1,766
  • 14
  • 20
kashif
  • 3,713
  • 8
  • 32
  • 47
  • 9
    This is not correct. The `==` operator can be overloaded for any type, not just string. Describing a special-case exception only for string misrepresents the operator's semantics. It would be more accurate, though perhaps not terribly useful, to say "if operands are reference types it returns true if the operands refer to the same object, unless there is an applicable overload, in which case the implementation of that overload determines the result". The same is true for `Equals` with the added complication that it is a virtual method, so its behavior can be overridden as well as overloaded. – phoog Jan 08 '15 at 16:35
  • a variable can be both a value type and a reference type. for example object i1 = 50; object i2 = 50. So at compile time (which is by default what matters for ==) they are both objects or reference types, so i1 == i2 will return a false; but at runtime (which is by default what matters for Equals) their actual value is both 50 or value type, so i1.Equals(i2) will return a true. quirky little edge case, but that's how it goes with c#. – LongChalk Jun 06 '22 at 10:55
31

As far as I understand it the answer is simple:

  1. == compares object references.
  2. .Equals compares object content.
  3. String datatypes always act like content comparison.

I hope I'm correct and that it answered your question.

Yousha Aleayoub
  • 4,532
  • 4
  • 53
  • 64
Liraz Shaka Amir
  • 587
  • 9
  • 26
21

Firstly, there is a difference. For numbers

> 2 == 2.0
True

> 2.Equals(2.0)
False

And for strings

> string x = null;
> x == null
True

> x.Equals(null)
NullReferenceException

In both cases, == behaves more usefully than .Equals

Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
  • 3
    I'm not sure I'd regard the coercion of integral types to floating-point types with the `==` operator to be a good thing. For example, should 16777216.0f equal (int)16777217, (double)16777217.0, both, or neither? Comparisons among integral types are fine, but floating-point comparisons should only be performed IMHO with values that are explicitly cast to matching types. The comparison of a `float` to something other than a `float`, or a `double` to something other than a `double`, strikes me as a major code smell that should not compile without diagnostics. – supercat Aug 16 '13 at 20:20
  • 1
    @supercat I agree—it's distressing that `x == y` does not imply `x/3 == y/3` (try `x = 5` and `y = 5.0`). – Colonel Panic Aug 19 '13 at 08:24
  • I consider the use of `/` for integer division to be a defect in the design of C# and Java. Pascal's `div` and even VB.NET's `\` are much better. The problems with `==` are worse, though: `x==y` and `y==z` does not imply that `x==z` (consider the three numbers in my previous comment). As for the relation you suggest, even if `x` and `y` are both `float` or both `double`, `x.equals((Object)y)` does not imply that `1.0f/x == `1.0f/y` (if I had my druthers, it would guarantee that; even if `==` doesn't distinguish positive and zero, `Equals` should). – supercat Aug 23 '13 at 21:20
  • That's normal, because Equals()'s first parameter is a string! – Whiplash Dec 12 '16 at 20:31
15

I would add that if you cast your object to a string then it will work correctly. This is why the compiler will give you a warning saying:

Possible unintended reference comparison; to get a value comparison, cast the left hand side to type 'string'

akjoshi
  • 15,374
  • 13
  • 103
  • 121
MikeKulls
  • 2,979
  • 2
  • 25
  • 30
  • 1
    Exactly. @DominicCronin: Always observe the compile-time warnings. If you have `object expr = XXX; if (expr == "Energy") { ... }`, then since the left-hand side is of compile-time type `object`, the compiler has to use the overload `operator ==(object, object)`. It checks for reference equality. Whether that will give `true` or `false` can be hard to predict because of [string interning](http://en.wikipedia.org/wiki/String_interning). If you _know_ the left-hand side is either `null` or of type `string`, cast the left-hand side to `string` before using `==`. – Jeppe Stig Nielsen Feb 13 '14 at 09:46
  • to put part of that another way. == (in determining whether it uses reference equality or value equality) depends on the compile time type/static type/left hand side type. (that's the type that is resolved in a compile time analysis). Rather than the runtime type/dynamic type/RHS type. BlueMonkMN's code shows that, though not with casting. – barlop Apr 22 '14 at 12:53
7

Because the static version of the .Equal method was not mentioned so far, I would like to add this here to summarize and to compare the 3 variations.

MyString.Equals("Somestring"))          //Method 1
MyString == "Somestring"                //Method 2
String.Equals("Somestring", MyString);  //Method 3 (static String.Equals method) - better

where MyString is a variable that comes from somewhere else in the code.

Background info and to summerize:

In Java using == to compare strings should not be used. I mention this in case you need to use both languages and also to let you know that using == can also be replaced with something better in C#.

In C# there's no practical difference for comparing strings using Method 1 or Method 2 as long as both are of type string. However, if one is null, one is of another type (like an integer), or one represents an object that has a different reference, then, as the initial question shows, you may experience that comparing the content for equality may not return what you expect.

Suggested solution:

Because using == is not exactly the same as using .Equals when comparing things, you can use the static String.Equals method instead. This way, if the two sides are not the same type you will still compare the content and if one is null, you will avoid the exception.

   bool areEqual = String.Equals("Somestring", MyString);  

It is a little more to write, but in my opinion, safer to use.

Here is some info copied from Microsoft:

public static bool Equals (string a, string b);

Parameters

a String

The first string to compare, or null.

b String

The second string to compare, or null.

Returns Boolean

true if the value of a is the same as the value of b; otherwise, false. If both a and b are null, the method returns true.

Community
  • 1
  • 1
Mario Levesque
  • 1,017
  • 13
  • 13
7

Just as an addition to the already good answers: This behaviour is NOT limited to Strings or comparing different numbertypes. Even if both elements are of type object of the same underlying type. "==" won't work.

The following screenshot shows the results of comparing two object {int} - values

Example From VS2017

Ole Albers
  • 8,715
  • 10
  • 73
  • 166
2

Adding one more point to the answer.

.EqualsTo() method gives you provision to compare against culture and case sensitive.

shA.t
  • 16,580
  • 5
  • 54
  • 111
Bala
  • 105
  • 8
2

There is another dimension to an earlier answer by @BlueMonkMN. The additional dimension is that the answer to the @Drahcir's title question as it is stated also depends on how we arrived at the string value. To illustrate:

string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
string s5 = "te" + "st";
object s6 = s5;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));

Console.WriteLine("\n  Case1 - A method changes the value:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));

Console.WriteLine("\n  Case2 - Having only literals allows to arrive at a literal:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));

The output is:

True True True

  Case1 - A method changes the value:
False True True
False False True

  Case2 - Having only literals allows to arrive at a literal:
True True True
True True True
CodeSmile
  • 64,284
  • 20
  • 132
  • 217
Novichok
  • 42
  • 3
2

I am a bit confused here. If the runtime type of Content is of type string, then both == and Equals should return true. However, since this does not appear to be the case, then runtime type of Content is not string and calling Equals on it is doing a referential equality and this explains why Equals("Energy Attack") fails. However, in the second case, the decision as to which overloaded == static operator should be called is made at compile time and this decision appears to be ==(string,string). this suggests to me that Content provides an implicit conversion to string.

Mehmet Aras
  • 5,284
  • 1
  • 25
  • 32
  • 2
    You have it back to front. For a start Equals("Energy Attack") does not fail, == is the one that returns false. The == fails because it is using the == from object, not string. – MikeKulls Aug 11 '11 at 03:33
  • 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. – Wajeed Shaikh Dec 30 '11 at 06:14
1

Really great answers and examples!

I would just like to add the fundamental difference between the two,

Operators such as == are not polymorphic, while Equals is

With that concept in mind, if you work out any example (by looking at left hand and right hand reference type, and checking/knowing if the type actually has == operator overloaded and Equals being overriden) you are certain to get the right answer.

Manish Basantani
  • 16,931
  • 22
  • 71
  • 103
1

This is due to value equality (equal method) and referential equality(== operator), as the equal method checks the values while the same == is checked the reference.

== operator overriding code available inside the string class on https://referencesource.microsoft.com/

so now it's easier to understand, the equal method also has 2 implementations one from the string class itself and one from the object class. its impact on performance as well I also run some basic code and try to understand the benchmarks.

I am sharing the results below Please correct or advise if I am wrong somewhere. there are 3 cases and I have run the same code for all the cases and this is the result.

case 1: here I am using string. equal method for comparing 2 strings and both the string have the same values. string.equals(a,b)

1st run:5608195 ticks

2nd run:5529387 ticks

3rd run:5622569 ticks

total ticks: 16760151

case 2: here I am using string. equal() method(overloaded one) for comparing 2 strings and both the string have the same values. a.equals(b)

1st run: 6738583 ticks

2nd run: 6452927 ticks

3rd run: 7168897 ticks

total ticks=20360407

case 3: here I am using the == operator for comparing 2 strings and both the string have the same values. a==b

1st run: 6652151 ticks

2nd run: 7514300 ticks

3rd run: 7634606 ticks

total ticks=21801057

class Program
{
    private static int count;
    static string a = "abcdef";
    static string b = "abcdef";
    static void Main(string[] args)
    {            

        for (int j = 1; j <= 3; j++)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 1; i <= 1000; i++)
            {
                checkString();
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedTicks);
        }
        Console.ReadLine();

    }
    public static void checkString()
    {
        for (int i = 1; i <= 100000; i++)
        {
            if (a==b)
                count++;
        }
    }
}
SiwachGaurav
  • 1,918
  • 2
  • 17
  • 16
0

The == token in C# is used for two different equality-check operators. When the compiler encounters that token, it will check whether either of the types being compared has implemented an equality-operator overload for either the specific combination types being compared(*), or for a combination of types to which both types can be converted. If the compiler finds such an overload it will use it. Otherwise, if the two types are both reference types and they are not unrelated classes (either may be an interface, or they may be related classes), the compiler will regard == as a reference-comparison operator. If neither condition applies, compilation will fail.

Note that some other languages use separate tokens for the two equality-check operators. In VB.NET, for example, the = token is used within expressions solely for the overloadable equality-check operator, and Is is used as a reference-test or null-test operator. An to use = on a type which does not override the equality-check operator will fail, as will attempting to use Is for any purpose other than testing reference equality or nullity.

(*)Types generally only overload equality for comparison with themselves, but it may be useful for types to overload the equality operator for comparison with other particular types; for example, int could have (and IMHO should have but didn't) defined an equality operators for comparison with float, so that 16777217 would not report itself equal to 16777216f. As it is, since no such operator is defined, C# will promote the int to float, rounding it to 16777216f before the equality-check operator sees it; that operator then sees two equal floating-point numbers and reports them as equal, unaware of the rounding that took place.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • Rather than having an int-to-float comparison return false, I prefer the approach that F# uses, which is to disallow such a comparison at all. Then the programmer can decide whether and how to handle the fact that the values have different type. Because sometimes, after all, we *do* want to treat `3` as being equal to `3.0f`. If we require the programmer to say what is intended in every case, then there is no danger of default behavior leading to unintended results, since there is no default behavior. – phoog Jan 08 '15 at 17:27
  • @phoog: My personal feeling is that languages should have their "normal" means of equality testing implement an equivalence relation, and forbid all combinations of operands for which it would not. I don't see a huge advantage of having a language check equality between integers and floats by confirming that a float precisely represents a whole number that matches the int, versus simply forbidding such comparisons, but would consider either approach superior to having the language perform a lossy conversion before the comparison. – supercat Jan 12 '15 at 17:06
0

Note that there are two different types of equality in C#

1- Value Equality (For value types like int, DateTime and struct)

2- Reference Equality (For objects)

There are two basic standard protocols for implement equality checks.

1- The == and != operators.

2- The virtual Equals method.

The == and != are statically resolve, which means C# will make a compile-time decision as to which type will perform the comparison.

For instance the value-type

 int x = 50;
 int y = 50;
 Console.WriteLine (x == y); // True

but for reference type

 object x = 50;
 object y = 50;
 Console.WriteLine (x == y); // False 

The Equals() originally resoled at runtime according to operand actual type.

For instance, in the following example, at runtime, it will be decided that the Equals() will apply on int values, the result is true.

object x = 5;
object y = 5;
Console.WriteLine (x.Equals (y)); // True

However, for a reference type, it will use a reference equality check.

MyObject x = new MyObject();
MyObject y = x;
Console.WriteLine (x.Equals (y)); // True

Note that Equals() uses structural comparison for struct, which means it calls Equals on each field of a struct.

0

Whether Equals() and == are the same depends on the implementation. Because C# allows users to set different behaviors for Equals() and == respectively.

    class CompareTest
    {
        public readonly int val;

        public CompareTest(int val)
        {
            this.val = val;
        }

        public override bool Equals(object obj)
        {
            return obj is CompareTest test && this.val == test.val;
        }

        public override int GetHashCode()
        {
            return val;
        }

        public static bool operator == (CompareTest a, object b)
        {
            return Equals(a, b);
        }

        public static bool operator != (CompareTest a, object b)
        {
            return !(a == b);
        }
    }

In this example, I made Equals() and == have the same behavior. But what if I make them different? For example:

        public static bool operator == (CompareTest a, object b)
        {
            return false;
        }

Equals() works normally but == will never works.

Furthermore, although I made them have the same behavior, but there is still one difference: which == function will be called depends on the left value:

        Compare Test a = new CompareTest(1);
        object b = new CompareTest(1);
        CompareTest c = new CompareTest(1);
        Debug.Log("AB " + (a == b)); // true
        Debug.Log("BA " + (b == a)); // false! because it calls object's == function 
        Debug.Log("AC " + (a == c)); // true
        Debug.Log("CA " + (c == a)); // true
Kenvix Zure
  • 191
  • 1
  • 7
-1

When we create any object there are two parts to the object one is the content and the other is reference to that content. == compares both content and reference; equals() compares only content

http://www.codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq

CT Zhu
  • 52,648
  • 17
  • 120
  • 133
  • 1
    This is not true. If `a` and `b` are both string references, then the result of `a == b` does not depend on whether the references point to the same object. – phoog Jan 08 '15 at 16:39
-2

==

The == operator can be used to compare two variables of any kind, and it simply compares the bits.

int a = 3;
byte b = 3;
if (a == b) { // true }

Note : there are more zeroes on the left side of the int but we don't care about that here.

int a (00000011) == byte b (00000011)

Remember == operator cares only about the pattern of the bits in the variable.

Use == If two references (primitives) refers to the same object on the heap.

Rules are same whether the variable is a reference or primitive.

Foo a = new Foo();
Foo b = new Foo();
Foo c = a;

if (a == b) { // false }
if (a == c) { // true }
if (b == c) { // false }

a == c is true a == b is false

the bit pattern are the same for a and c, so they are equal using ==.

Equal():

Use the equals() method to see if two different objects are equal.

Such as two different String objects that both represent the characters in "Jane"

Sanchit
  • 1,145
  • 11
  • 6
  • 2
    This is incorrect. Consider the following: `object a = 3; object b = 3; Console.WriteLine(a == b);`. The output is false, even though the bit patterns of the values are the same. The types of the operands also matter. The reason we "don't care" about the different number of zeros in your example is that by the time we call the equals operator, the number of zeros is *actually the same*, because of implicit conversion. – phoog Jan 08 '15 at 17:11
-2

The only difference between Equal and == is on object type comparison. in other cases, such as reference types and value types, they are almost the same(either both are bit-wise equality or both are reference equality).

object: Equals: bit-wise equality ==: reference equality

string: (equals and == are the same for string, but if one of string changed to object, then comparison result will be different) Equals: bit-wise equality == : bit-wise equality

See here for more explanation.

Will Yu
  • 546
  • 5
  • 12
  • Object.Equals does not necessarily look at bitwise equality. It is a virtual method, and an override can do whatever it wants. – phoog Jan 08 '15 at 16:44
  • yes, you are right, you can do whatever you want to override it. but the topic we are talking is the default implementation. the default implementation of Object.Equals is bit-wise equality. – Will Yu Jan 08 '15 at 18:14