Differences in string compare methods in C# - c#

Comparing string in C# is pretty simple. In fact there are several ways to do it. I have listed some in the block below. What I am curious about are the differences between them and when one should be used over the others? Should one be avoided at all costs? Are there more I haven't listed?
string testString = "Test";
string anotherString = "Another";
if (testString.CompareTo(anotherString) == 0) {}
if (testString.Equals(anotherString)) {}
if (testString == anotherString) {}
(Note: I am looking for equality in this example, not less than or greater than but feel free to comment on that as well)

Here are the rules for how these functions work:
stringValue.CompareTo(otherStringValue)
null comes before a string
it uses CultureInfo.CurrentCulture.CompareInfo.Compare, which means it will use a culture-dependent comparison. This might mean that ß will compare equal to SS in Germany, or similar
stringValue.Equals(otherStringValue)
null is not considered equal to anything
unless you specify a StringComparison option, it will use what looks like a direct ordinal equality check, i.e. ß is not the same as SS, in any language or culture
stringValue == otherStringValue
Is not the same as stringValue.Equals().
The == operator calls the static Equals(string a, string b) method (which in turn goes to an internal EqualsHelper to do the comparison.
Calling .Equals() on a null string gets null reference exception, while on == does not.
Object.ReferenceEquals(stringValue, otherStringValue)
Just checks that references are the same, i.e. it isn't just two strings with the same contents, you're comparing a string object with itself.
Note that with the options above that use method calls, there are overloads with more options to specify how to compare.
My advice if you just want to check for equality is to make up your mind whether you want to use a culture-dependent comparison or not, and then use .CompareTo or .Equals, depending on the choice.

From MSDN:
"The CompareTo method was designed primarily for use in sorting or
alphabetizing operations. It should not be used when the primary
purpose of the method call is to determine whether two strings are
equivalent. To determine whether two strings are equivalent, call
the Equals method."
They suggest using .Equals instead of .CompareTo when looking solely for equality. I am not sure if there is a difference between .Equals and == for the string class. I will sometimes use .Equals or Object.ReferenceEquals instead of == for my own classes in case someone comes along at a later time and redefines the == operator for that class.

If you are ever curious about differences in BCL methods, Reflector is your friend :-)
I follow these guidelines:
Exact match: EDIT: I previously always used == operator on the principle that inside Equals(string, string) the object == operator is used to compare the object references but it seems strA.Equals(strB) is still 1-11% faster overall than string.Equals(strA, strB), strA == strB, and string.CompareOrdinal(strA, strB). I loop tested with a StopWatch on both interned/non-interned string values, with same/different string lengths, and varying sizes (1B to 5MB).
strA.Equals(strB)
Human-readable match (Western cultures, case-insensitive):
string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0
Human-readable match (All other cultures, insensitive case/accent/kana/etc defined by CultureInfo):
string.Compare(strA, strB, myCultureInfo) == 0
Human-readable match with custom rules (All other cultures):
CompareOptions compareOptions = CompareOptions.IgnoreCase
| CompareOptions.IgnoreWidth
| CompareOptions.IgnoreNonSpace;
string.Compare(strA, strB, CultureInfo.CurrentCulture, compareOptions) == 0

As Ed said, CompareTo is used for sorting.
There is a difference, however, between .Equals and ==.
== resolves to essentially the following code:
if(object.ReferenceEquals(left, null) &&
object.ReferenceEquals(right, null))
return true;
if(object.ReferenceEquals(left, null))
return right.Equals(left);
return left.Equals(right);
The simple reason is the following will throw an exception:
string a = null;
string b = "foo";
bool equal = a.Equals(b);
And the following will not:
string a = null;
string b = "foo";
bool equal = a == b;

Good explanation and practices about string comparison issues may be found in the article New Recommendations for Using Strings in Microsoft .NET 2.0 and also in Best Practices for Using Strings in the .NET Framework.
Each of mentioned method (and other) has particular purpose. The key difference between them is what sort of StringComparison Enumeration they are using by default. There are several options:
CurrentCulture
CurrentCultureIgnoreCase
InvariantCulture
InvariantCultureIgnoreCase
Ordinal
OrdinalIgnoreCase
Each of above comparison type targets different use case:
Ordinal
Case-sensitive internal identifiers
Case-sensitive identifiers in standards like XML and HTTP
Case-sensitive security-related settings
OrdinalIgnoreCase
Case-insensitive internal identifiers
Case-insensitive identifiers in standards like XML and HTTP
File paths (on Microsoft Windows)
Registry keys/values
Environment variables
Resource identifiers (handle names, for example)
Case insensitive security related settings
InvariantCulture or InvariantCultureIgnoreCase
Some persisted linguistically-relevant data
Display of linguistic data requiring a fixed sort order
CurrentCulture or CurrentCultureIgnoreCase
Data displayed to the user
Most user input
Note, that StringComparison Enumeration as well as overloads for string comparison methods, exists since .NET 2.0.
String.CompareTo Method (String)
Is in fact type safe implementation of IComparable.CompareTo Method. Default interpretation: CurrentCulture.
Usage:
The CompareTo method was designed primarily for use in sorting or alphabetizing operations
Thus
Implementing the IComparable interface will necessarily use this method
String.Compare Method
A static member of String Class which has many overloads. Default interpretation: CurrentCulture.
Whenever possible, you should call an overload of the Compare method that includes a StringComparison parameter.
String.Equals Method
Overriden from Object class and overloaded for type safety. Default interpretation: Ordinal.
Notice that:
The String class's equality methods include the static Equals, the static operator ==, and the instance method Equals.
StringComparer class
There is also another way to deal with string comparisons especially aims to sorting:
You can use the StringComparer class to create a type-specific comparison to sort the elements in a generic collection. Classes such as Hashtable, Dictionary, SortedList, and SortedList use the StringComparer class for sorting purposes.

Not that performance usually matters with 99% of the times you need to do this, but if you had to do this in a loop several million times I would highly suggest that you use .Equals or == because as soon as it finds a character that doesn't match it throws the whole thing out as false, but if you use the CompareTo it will have to figure out which character is less than the other, leading to slightly worse performance time.
If your app will be running in different countries, I'd recommend that you take a look at the CultureInfo implications and possibly use .Equals. Since I only really write apps for the US (and don't care if it doesn't work properly by someone), I always just use ==.

In the forms you listed here, there's not much difference between the two. CompareTo ends up calling a CompareInfo method that does a comparison using the current culture; Equals is called by the == operator.
If you consider overloads, then things get different. Compare and == can only use the current culture to compare a string. Equals and String.Compare can take a StringComparison enumeration argument that let you specify culture-insensitive or case-insensitive comparisons. Only String.Compare allows you to specify a CultureInfo and perform comparisons using a culture other than the default culture.
Because of its versatility, I find I use String.Compare more than any other comparison method; it lets me specify exactly what I want.

One BIG difference to note is .Equals() will throw an exception if first string is null, Whereas == will not.
string s = null;
string a = "a";
//Throws {"Object reference not set to an instance of an object."}
if (s.Equals(a))
Console.WriteLine("s is equal to a");
//no Exception
if(s==a)
Console.WriteLine("s is equal to a");

s1.CompareTo(s2): Do NOT use if primary purpose is to determine whether two strings are equivalent
s1 == s2: Cannot ignore case
s1.Equals(s2, StringComparison): Throws NullReferenceException if s1 is null
String.Equals(s2, StringComparison): By process of eliminiation, this static method is the WINNER (assuming a typical use case to determine whether two strings are equivalent)!

Using .Equals is also a lot easier to read.

with .Equals, you also gain the StringComparison options. very handy for ignoring case and other things.
btw, this will evaluate to false
string a = "myString";
string b = "myString";
return a==b
Since == compares the values of a and b (which are pointers) this will only evaluate to true if the pointers point to the same object in memory. .Equals dereferences the pointers and compares the values stored at the pointers.
a.Equals(b) would be true here.
and if you change b to:
b = "MYSTRING";
then a.Equals(b) is false, but
a.Equals(b, StringComparison.OrdinalIgnoreCase)
would be true
a.CompareTo(b) calls the string's CompareTo function which compares the values at the pointers and returns <0 if the value stored at a is less than the value stored at b, returns 0 if a.Equals(b) is true, and >0 otherwise. However, this is case sensitive, I think there are possibly options for CompareTo to ignore case and such, but don't have time to look now.
As others have already stated, this would be done for sorting. Comparing for equality in this manner would result in unecessary overhead.
I'm sure I'm leaving stuff out, but I think this should be enough info to start experimenting if you need more details.

Related

Why do string datatypes always perform value comparison

I was looking for the difference between == and .Equals methods in C# and I found that the first one compares the object references, and the second one compares the objects values, except for the string datatypes both == and .Equals() does a content comparison. I can't really find an explanation for that, is it because the string datatypes are immutable ?
Here's what I want to say
object obj1 = "Test";
object obj2 = new string("Test".ToCharArray());
Console.WriteLine(obj1.Equals(obj2) + " " + (obj1 == obj2));
string a = "Test";
string b = "Test";
Console.WriteLine(a.Equals(b) + " "+ (a == b));
Output
True False
True True
In fact for the first comparison we have two different objects with same value and we got as result True and false, but for the case of string we have true for both comparison
This isn't true at all. == is an overridable operator, and Equals is an overridable method. It's up to the class to define how each of them behaves.
Perhaps you're confusing C# with Java?
If you want to do a reference comparison, use object.ReferenceEquals. Everything else is implementation dependant (though note that operator overrides are checked statically, so e.g. (object)someString == (object)someOtherString will do a reference comparison, not a value comparison; Equals doesn't have this "problem").
Most often, both == and Equals are designed to give the same answer (though == is always stricter about types in the comparison, as mentioned before). This applies double for structs, where a reference comparison doesn't really make much of a sense anyway.
And of course, the compiler doesn't actually do any checks. If I want, I can override the == operator to always return false. Or to only check some ID for equality. Or to change the objects being compared, if you are feeling particularly evil. In the end, it's just a static method like any other (with a few restrictions).
EDIT:
To address your edit directly, string always performs a content comparison because both its == and Equals are overriden to perform a content comparison. However, that doesn't mean that it always performs a costly char-by-char comparison - if you look how string.Equals is actually implemented, you can see that it tries a few things to avoid the costly comparison:
If the string is null, they must be different
If the two strings are reference-equal, they must also be content-equal
If the two strings don't have the same length, they must be different
You can see the actual by-value comparison method here - http://referencesource.microsoft.com/#mscorlib/system/string.cs,11648d2d83718c5e A simple piece of unsafe code, but manually written code nevertheless. There's no automatic value comparison in .NET (though there's tricks that come close).
It's because it makes sense.
Java couldn't do it this way because it doesn't have operator overloading, but that's no argument in C#.
This isn't unique to strings, by the way. Any type could overload the == operator to do something similar.
Any object can override/overload Equals or ==, so they can behave however the library author wants them to behave.

How to check if Dictionary already has a key 'x'?

I am trying to implement simple algorithm with use of C#'s Dictionary :
My 'outer' dictionary looks like this : Dictionary<paramID, Dictionary<string, object>> [where paramID is simply an identifier which holds 2 strings]
if key 'x' is already in the dictionary then add specific entry to this record's dictionary, if it doesn't exist then add its entry to the outer Dictionary and then add entry to the inner dictionary.
Somehow, when I use TryGetValue it always returns false, therefore it always creates new entries in the outer Dictionary - what produces duplicates.
My code looks more or less like this :
Dictionary<string, object> tempDict = new Dictionary<string, object>();
if(outerDict.TryGetValue(new paramID(xKey, xValue), out tempDict))
{
tempDict.Add(newKey, newValue);
}
Block inside the ifis never executed, even if there is this specific entry in the outer Dictionary.
Am I missing something ? (If you want I can post screen shots from debugger - or something else if you desire)
If you haven't over-ridden equals and GetHashCode on your paramID type, and it's a class rather than a struct, then the default equality meaning will be in effect, and each paramID will only be equal to itself.
You likely want something like:
public class ParamID : IEquatable<ParamID> // IEquatable makes this faster
{
private readonly string _first; //not necessary, but immutability of keys prevents other possible bugs
private readonly string _second;
public ParamID(string first, string second)
{
_first = first;
_second = second;
}
public bool Equals(ParamID other)
{
//change for case-insensitive, culture-aware, etc.
return other != null && _first == other._first && _second == other._second;
}
public override bool Equals(object other)
{
return Equals(other as ParamID);
}
public override int GetHashCode()
{
//change for case-insensitive, culture-aware, etc.
int fHash = _first.GetHashCode();
return ((fHash << 16) | (fHash >> 16)) ^ _second.GetHashCode();
}
}
For the requested explanation, I'm going to do a different version of ParamID where the string comparison is case-insensitive and ordinal rather than culture based (a form that would be appropriate for some computer-readable codes (e.g. matching keywords in a case-insensitive computer language or case-insensitive identifiers like language tags) but not for something human-readable (e.g. it will not realise that "SS" is a case-insensitive match to "ß"). This version also considers {"A", "B"} to match {"B", "A"} - that is, it doesn't care what way around the strings are. By doing a different version with different rules it should be possible to touch on a few of the design considerations that come into play.
Let's start with our class containing just the two fields that are it's state:
public class ParamID
{
private readonly string _first; //not necessary, but immutability of keys prevents other possible bugs
private readonly string _second;
public ParamID(string first, string second)
{
_first = first;
_second = second;
}
}
At this point if we do the following:
ParamID x = new ParamID("a", "b");
ParamID y = new ParamID("a", "b");
ParamID z = x;
bool a = x == y;//a is false
bool b = z == x;//b is true
Because by default a reference type is only equal to itself. Why? Well firstly, sometimes that's just what we want, and secondly it isn't always clear what else we might want without the programmer defining how equality works.
Note also, that if ParamID was a struct, then it would have equality defined much like what you wanted. However, the implementation would be rather inefficient, and also buggy if it contained a decimal, so either way it's always a good idea to implement equality explicitly.
The first thing we are going to do to give this a different concept of equality is to override IEquatable<ParamID>. This is not strictly necessary, (and didn't exist until .NET 2.0) but:
It will be more efficient in a lot of use cases, including when key to a Dictionary<TKey, TValue>.
It's easy to do the next step with this as a starting point.
Now, there are four rules we must follow when we implement an equality concept:
An object must still be always equal to itself.
If X == Y and X != Z, then later if the state of none of those objects has changed, X == Y and X != Z still.
If X == Y and Y == Z, then X == Z.
If X == Y and Y != Z then X != Z.
Most of the time, you'll end up following all these rules without even thinking about it, you just have to check them if you're being particularly strange and clever in your implementation. Rule 1 is also something that we can take advantage of to give us a performance boost in some cases:
public class ParamID : IEquatable<ParamID>
{
private readonly string _first; //not necessary, but immutability of keys prevents other possible bugs
private readonly string _second;
public ParamID(string first, string second)
{
_first = first;
_second = second;
}
public bool Equals(ParamID other)
{
if(other == null)
return false;
if(ReferenceEquals(this, other))
return true;
if(string.Compare(_first, other._first, StringComparison.InvariantCultureIgnoreCase) == 0 && string.Compare(_second, other._second, StringComparison.InvariantCultureIgnoreCase) == 0)
return true;
return string.Compare(_first, other._second, StringComparison.InvariantCultureIgnoreCase) == 0 && string.Compare(_second, other._first, StringComparison.InvariantCultureIgnoreCase) == 0;
}
}
The first thing we've done is see if we're being compared with equality to null. We almost always want to return false in such cases (not always, but the exceptions are very, very rare and if you don't know for sure you're dealing with such an exception, you almost certainly are not), and certainly we don't want to throw a NullReferenceException.
The next thing we do is to see if the object is being compared with itself. This is purely an optimisation. In this case, it's probably a waste of time, but it can be very useful with more complicated equality tests, so it's worth pointing out this trick here. This takes advantage of the rule that identity entails equality, that is, any object is equal to itself (Ayn Rand seemed to think this was somehow profound).
Finally, having dealt with these two special cases, we get to the actual rule for equality. As I said above, my example considers two objects equal if they have the same two strings, in either order, for case-insensitive ordinal comparisons, so I've a bit of code to work that out.
(Note that the order in which we compare component parts can have a performance impact. Not in this case, but with a class that contains both an int and a string we would compare the ints first because is faster and we will hence perhaps find an answer of false before we even look at the strings)
Now at this point we've a good basis for overriding the Equals method defined in object:
public override bool Equals(object other)
{
return (other as ParamID);
}
Since as will return a ParamID reference if other is a ParamID and null for anything else (including if null was what we were passed in the first place), and since we already handle comparison with null, we're all set.
Try to compile at this point and you will get a warning that you have overriden Equals but not GetHashCode (the same is true if you'd done it the other way around).
GetHashCode is used by the dictionary (and other hash-based collections like HashTable and HashSet) to decide where to place the key internally. It will take the hashcode, re-hash it down to a smaller value in a way that is its business, and use it to place the object in its internal store.
Because of this, it's clear why the following is a bad idea were ParamID not readonly on all fields:
ParamID x = new ParamID("a", "b");
dict.Add(x, 33);
x.First = "c";//x will now likely never be found in dict because its hashcode doesn't match its position!
This means the following rules apply to hash-codes:
Two objects considered equal, must have the same hashcode. (This is a hard rule, you will have bugs if you break it).
While we can't guarantee uniqueness, the more spread out the returned results, the better. (Soft rule, you will have better performance the better you do at it).
(Well, 2½.) While not a strict rule, if we take such a complicated approach to point 2 above that it takes forever to return a result, the nett effect will be worse than if we had a poorer-quality hash. So we want to try to be reasonably quick too if we can.
Despite the last point, it's rarely worth memoising the results. Hash-based collections will normally memoise the value themselves, so it's a waste to do so in the object.
For the first implementation, because our approach to equality depended upon the default approach to equality of the strings, we could use strings default hashcode. For my different version I'll use another approach that we'll explore more later:
public override int GetHashCode()
{
return StringComparer.OrdinalIgnoreCase.GetHashCode(_first) ^ StringComparer.OrdinalIgnoreCase.GetHashCode(_second);
}
Let's compare this to the first version. In both cases we get hashcodes of the component parts. If the values where integers, chars or bytes we would have worked with the values themselves, but here we build on the work done in implementing the same logic for those parts. In the first version we use the GetHashCode of string itself, but since "a" has a different hashcode to "A" that won't work here, so we use a class that produces a hashcode ignoring that difference.
The other big difference between the two is that in the first case we mix the bits up more with ((fHash << 16) | (fHash >> 16)). The reason for this is to avoid duplicate hashes. We can't produce a perfect hashcode where every different object has a different value, because there are only 4294967296 possible hashcode values, but many more possible values for ParamID (including null, which is treated as having a hashcode of 0). (There are cases where prefect hashes are possible, but they bring in different concerns than here). Because of this imperfection we have to think not only about what values are possible, but which are likely. Generally, shifting bits like we've done in the first version avoids common values having the same hash. We don't want {"A", "B"} to hash the same as {"B", "A"}.
It's an interesting experiment to produce a deliberately poor GetHashCode that always returns 0, it'll work, but instead of being close to O(1), dictionaries will be O(n), and poor as O(n) goes for that!
The second version doesn't do that, because it has different rules so for it we actually want to consider values the same but for being switch around as equal, and hence with the same hashcode.
The other big difference is the use of StringComparer.OrdinalIgnoreCase. This is an instance of StringComparer which, among other interfaces, implements IEqualityComparer<string> and IEqualityComparer. There are two interesting things about the IEqualityComparer<T> and IEqualityComparer interfaces.
The first is that hash-based collections (such as dictionary) all use them, it's just that unless passed an instance of one to their constructor they will use DefaultEqualityComparer which calls into the Equals and GetHashCode methods we've described above.
The other, is that it allows us to ignore the Equals and GetHashCode mentioned above, and provide them from another class. There are three advantages to this:
We can use them in cases (string is a classic case) where there is more than one likely definition of "equals".
We can ignore that by the class' author, and provide our own.
We can use them to avoid a particular attack. This attack is based on being in a situation where input you provide will be hashed by the code you are attacking. You pick input so as to deliberately provide objects that are different, but hash the same. This means that the poor performance we talked about avoiding earlier is hit, and it can be so bad that it becomes a denial of service attack. By providing different IEqualityComparer implementations with random elements to the hash code (but the same for every instance of the comparer) we can vary the algorithm enough each time as to twart the attack. The use for this is rare (it has to be something that will hash based purely on outside input that is large enough for the poor performance to really hurt), but vital when it comes up.
Finally. If we override Equals we may or may not want to override == and != too. It can be useful to keep them refering to identity only (there are times when that is what we care most about) but it can be useful to have them refer to other semantics (`"abc" == "ab" + "c" is an example of an override).
In summary:
The default equality of reference objects is identity (equal only to itself).
The default equality of value types is a simple comparison of all fields (but poor in performance).
We can change the concept of equality for our classes in either case, but this MUST involve both Equals and GetHashCode*
We can override this and provide another concept of equality.
Dictionary, HashSet, ConcurrentDictionary, etc. all depend on this.
Hashcodes represent a mapping from all values of an object to a 32-bit number.
Hashcodes must be the same for objects we consider equal.
Hashcodes must be spread well.
*Incidentally, anonymous classes have a simple comparison like that of value types, but better performance, which matches almost any case in which we mght care about the hash code of an anonymous type.
Most likely, paramID does not implement equality comparison correctly.
It should be implementing IEquatable<paramID> and that means especially that the GetHashCode implementation must adhere to the requirements (see "Notes to implementers").
As for keys in dictionaries, MSDN says:
As long as an object is used as a key in the Dictionary(Of TKey,
TValue), it must not change in any way that affects its hash value.
Every key in a Dictionary(Of TKey, TValue) must be unique according to
the dictionary's equality comparer. A key cannot be Nothing, but a
value can be, if the value type TValue is a reference type.
Dictionary(Of TKey, TValue) requires an equality implementation to
determine whether keys are equal. You can specify an implementation of
the IEqualityComparer(Of T) generic interface by using a constructor
that accepts a comparer parameter; if you do not specify an
implementation, the default generic equality comparer
EqualityComparer(Of T).Default is used. If type TKey implements the
System.IEquatable(Of T) generic interface, the default equality
comparer uses that implementation.
Since you don't show the paramID type I cannot go into more detail.
As an aside: that's a lot of keys and values getting tangled in there. There's a dictionary inside a dictionary, and the keys of the outer dictionary aggregate some kind of value as well. Perhaps this arrangement can be advantageously simplified? What exactly are you trying to achieve?
Use the Dictionary.ContainsKey method.
And so:
Dictionary<string, object> tempDict = new Dictionary<string, object>();
paramID searchKey = new paramID(xKey, xValue);
if(outerDict.ContainsKey(searchKey))
{
outerDict.TryGetValue(searchKey, out tempDict);
tempDict.Add(newKey, newValue);
}
Also don't forget to override the Equals and GetHashCode methods in order to correctly compare two paramIDs:
class paramID
{
// rest of things
public override bool Equals(object obj)
{
paramID p = (paramID)obj;
// how do you determine if two paramIDs are the same?
if(p.key == this.key) return true;
return false;
}
public override int GetHashCode()
{
return this.key.GetHashCode();
}
}

C# System.Object.operator==()

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.

How does .NET compiler compare two strings?

string a="I am comparing 2 string";
string b="I am comparing 2 string";
if(a==b)
return true;
else
return false;
How does a .NET compiler compare two strings? Does a string work like a struct(int)?
string is class so a=b means we are comparing 2 object, but i want to compare 2 values.
The String class overloads the == operator, so yes it compares the values of the strings, just like comparing value types like int.
(On a side note, the compiler also interns literal strings in the code, so the string variables a and b will actually be referencing the same string object. If you use Object.ReferenceEquals(a,b) it will also return true.)
System.String is a class which has the == operator overloaded to compare the content of the strings. This allows it to be "value like" in comparison and yet still be a reference type in other respects.
Although string is a reference type, the equality operators (== and !=) are defined to compare the values of string objects, not references. This makes testing for string equality more intuitive.
C# string
Strings are compared by the Runtime, not the compiler. Comparison is performed by Equality operator.
There are different things to keep in mind here.
First, all identical constant strings will be interned so that both references are equal to start with. Therefore, even if you did a ReferenceEquals() here, you'd get "true" as result. So only for a string built (for instance with a StringBuilder, or read from a file etc.) you'd get another reference and therefore false when doing a reference equality comparison.
If both objects are known to be strings at compile time, the compiler will emit code to compare their value (== overloaded operator on System.String), not their references. Note that as soon as you compare it against an object type reference, this isn't the case anymore.
No runtime check is done to compare a string by value, and the compiler does not emit a .Equals() call for the == operator.
Notice that your question is a little tricky. Because ReferenceEquals will ALSO return true.
This is because of Interning : http://en.wikipedia.org/wiki/String_interning

What is the difference between .Equals and == [duplicate]

This question already has answers here:
C# difference between == and Equals()
(20 answers)
Closed 9 years ago.
What is the difference between a.Equals(b) and a == b for value types, reference types, and strings? It would seem as though a == b works just fine for strings, but I'm trying to be sure to use good coding practices.
From When should I use Equals and when should I use ==:
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.
Value types do not provide an overload
for == by default. However, most of
the value types provided by the
framework provide their own overload.
The default implementation of Equals
for a value type is provided by
ValueType, and uses reflection to make
the comparison, which makes it
significantly slower than a
type-specific implementation normally
would be. This implementation also
calls Equals on pairs of references
within the two values being compared.
using System;
public class Test
{
static void Main()
{
// Create two equal but distinct strings
string a = new string(new char[] {'h', 'e', 'l', 'l', 'o'});
string b = new string(new char[] {'h', 'e', 'l', 'l', 'o'});
Console.WriteLine (a==b);
Console.WriteLine (a.Equals(b));
// Now let's see what happens with the same tests but
// with variables of type object
object c = a;
object d = b;
Console.WriteLine (c==d);
Console.WriteLine (c.Equals(d));
}
}
The result of this short sample program is
True
True
False
True
Here is a great blog post about WHY the implementations are different.
Essentially == is going to be bound at compile time using the types of the variables and .Equals is going to be dynamically bound at runtime.
In the most shorthand answer:
== opertator is to check identity. (i.e: a==b are these two are the same object?)
.Equals() is to check value. (i.e: a.Equals(b) are both holding identical values?)
With one exception:
For string and predefined value types (such as int, float etc..),
the operator == will answer for value and not identity. (same as using .Equals())
One significant difference between them is that == is a static binary operator that works on two instances of a type whereas Equals is an instance method. The reason this matters is that you can do this:
Foo foo = new Foo()
Foo foo2 = null;
foo2 == foo;
But you cannot do this without throwing a NullReferenceException:
Foo foo = new Foo()
Foo foo2 = null;
foo2.Equals(foo);
At a simple level, the difference is which method is called. The == method will attempt ot bind to operator== if defined for the types in question. If no == is found for value types it will do a value comparison and for reference types it will do a reference comparison. A .Equals call will do a virtual dispatch on the .Equals method.
As to what the particular methods do, it's all in the code. Users can define / override these methods and do anything they please. Ideally this methods should be equivalent (sorry for the pun) and have the same output but it is not always the case.
One simple way to help remember the difference is that a.Equals(b) is more analogous to
a == (object)b.
The .Equals() method is not generic and accepts an argument of type "object", and so when comparing to the == operator you have to think about it as if the right-hand operand were cast to object first.
One implication is that a.Equals(b) will nearly always return some value for a and b, regardless of type (the normal way to overload is to just return false if b is an unkown type). a == b will just throw an exception if there's no comparison available for those types.
"==" is an operator that can be overloaded to perform different things based on the types being compared.
The default operation performed by "==" is a.Equals(b);
Here's how you could overload this operator for string types:
public static bool operator == (string str1, string str2)
{
return (str1.Length == str2.Length;)
}
Note that this is different than str1.Equals(str2);
Derived classes can also override and redefine Equals().
As far as "best practices" go, it depends on your intent.
For strings you want to be careful of culture specific comparisons. The classic example is the german double S, that looks a bit like a b. This should match with "ss" but doesn't in a simple == comparison.
For string comparisons that are culture sensitive use: String.Compare(expected, value, StringComparison....) == 0 ? with the StringComparison overload you need.
By default, both == and .Equals() are equivalent apart from the possibility of calling .Equals() on a null instance (which would give you a NullReferenceException). You can, however, override the functionality of either of them independently (though I'm not sure that would ever be a good idea unless you're trying to work around the shortcomings of another system), which would mean you could MAKE them different.
You'll find people on both sides of the aisle as to the one to use. I prefer the operator rather than the function.
If you're talking about strings, though, it's likely a better idea to use string.Compare() instead of either one of those options.

Categories