Why strings does not compare references? - c#

I know it is special case but why == between strings returns if their value equals and not when their reference equals. Does it have something to do with overlloading operators?

The == operator is overloaded in String to perform value equality instead of reference equality, indeed. The idea is to make strings more friendly to the programmer and to avoid errors that arise when using reference equality to compare them (not too uncommon in Java, especially for beginners).
So far I have never needed to compare strings by reference, to be honest. If you need to do it you can use object.ReferenceEquals().

Because strings are immutable and the runtime may choose to put any two strings with the same content together into the same reference. So reference-comparing strings doesn't really make any sense.

Yes. From .NET Reflector here is the equality operator overloading of String class:
public static bool operator ==(string a, string b)
{
return Equals(a, b);
}

The equality operators (== and !=) are defined to compare the values of string objects, not references.
There was not any situation in which I had to compare the references but if you want to do so then you can use:
object.ReferenceEquals().

on a string, == compares by value
"Although string is a reference type, the equality operators (== and !=) are defined to compare the values of string objects, not references (7.9.7 String equality operators). This makes testing for string equality more intuitive."
In short, == on strings compares the strings by value, not by reference, because the C# specification says it should.

Related

C# RequireNonDefaultAttribute strange behaviour: Equals vs == inside IsValid() [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.

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)

Operator '>=' cannot be applied to operands of type 'string' and 'string'

I'm using Entity Framework in C# and my code is
var result = ef.services.Where(entry => entry.tarikhservice >= textBoxX1.Text
&& entry.tarikhservice <= textBoxX2.Text).ToList();
which gives me this error:
Operator '>=' cannot be applied to operands of type 'string' and 'string'
How to compare two string and fix the error?
When you compare numbers, say 1 and 2, it is clear which one is greater. However, when you compare strings, which one is considered greater: "2" or "11"? "foo" or "f"? Answer: it depends on context. For example if you sort them lexicographically, you get "2" and "f". If you want the natural sort, you would get "2" before "11".
I presume for that reason, relative operators (>, >=, <, <=) are not overloaded for string (which IMHO is a good decision).
Your option is to either write your custom logic to compare strings, or use a framework-provided lexicographical comparison. The code would be (if I got the numbers right):
var result = ef.services.Where(entry =>
string.Compare(entry.tarikhservice, textBoxX1.Text) >= 0
&& string.Compare(entry.tarikhservice, textBoxX2.Text) <= 0
.ToList()
To make code work regardless of culture (you should!), provide a StringComparison as last parameter to string.compare:
string.Compare(entry.tarikhservice, textBoxX1.Text, StringComparison.InvariantCulture)
I'm not sure I agree with the rationale given in the current answers for not implementing the comparison operators in String. In fact, I submit that implementing them using String.Compare would be just as consistent as the current equality operator implementation using String.Equals.
I have a different theory. If you examine the Best Practices for Using Strings in .NET you will note the following recommendation:
The String class lets you test for equality by calling either the
static or instance Equals method overloads, or by using the static
equality operator. The overloads and operator use ordinal comparison
by default. However, we still recommend that you call an overload that
explicitly specifies the StringComparison type even if you want to
perform an ordinal comparison
Note that they couldn't enforce this recommendation even if they wanted to - even if they didn't override the == operator in String, you could still do str1 == str2. Heck, you could compare an integer to a string using the equality operator if you really wanted to (obj i = 1). This is because == translates into reference equality when not overridden specifically for the operand types.
The BCL designers realized this and decided they would be better off implementing a comparison operator that works as expected most of the time, rather than delegate the comparison to reference equality, which would be a really bad idea considering string interning and Unicode equivalence.
Now, back to comparison operators. The same pitfalls with string equality apply, but the BCL designers have an easier time here. By simply not implementing these operators, the compiler does their job for them and, as we can see in this question, prevents devs from even trying to do things like str1 >= str2.
It is quite reasonable that you take. Two strings can be equal or not equal. Nothing less nothing more. The greater and the less operator makes sense, when you compare numbers, or if you compare objects for which you have overloaded this operators.
As it is stated here,
A string is not a number, so you're comparing lexicographically.
String.CompareTo is used for ordering.

ReferenceEquals(variable, null) is the same as variable == null?

Basically the title. I see a lot of the former in the code I'm working on and I was wondering why they didn't use the latter. Are there any differences between the two?
Thanks.
Straight from the documentation
Unlike the Equals method and the equality operator, the ReferenceEquals method cannot be overridden. Because of this, if you want to test two object references for equality and are unsure about the implementation of the Equals method, you can call the ReferenceEquals method. However, note that if objA and objB are value types, they are boxed before they are passed to the ReferenceEquals method.
Not really. One can overload operator ==, so you basically can get it return e.g. false always. The recommended usage for this operator is to signify value equality, so (for correcftly implemented operator) basically check against null may return true if the object is semantically null.
See this article for more details and some historical overview.
Another difference is that for value types ReferenceEquals doesn't make much sense: for example, any two "instances" of int 0 have to be considered the same in any sane circumstances. (For purists: I put quotes because, strictly speaking, we cannot talk about instances of a value type.)
The main benefit of ReferenceEquals() is that the intention is much clearer, you are trying to determine if two references are equal, not if the contents of the objects referred to are equal.
It does this by checking for operator == equality between the two references cast to object (since the params are both object), which eliminates any subclass operator == overloads that might confuse the issue (like string's).
So essentially, this:
if (ReferenceEquals(x, y))
Is the same as this:
if (((object)x) == ((object)y))
Though the former is easier to read.
There are definitely times where it comes in handy, especially avoiding infinite recursion when you are overloading operator == yourself:
public class Foo
{
public static bool operator ==(Foo first, Foo second)
{
// can't say if (first == second) here or infinite recursion...
if (ReferenceEquals(first, second))
{
// if same object, obviously same...
return true;
}
// etc.
}
}

Question about Object Identity and Object Equality and String class exception

This is a Java and C# question.
We all know that, Object Identity(==) tests whether two objects refer to the same location and Obejct Equality(Equals method) tests whether two different (non identical)objects have the same value .But In case of string object Object Identity and Object Equality are same.
For e.g Below two boolean expressions in if statements return true
string a="123";
string b="123";
if(a==b)
if(a.Equals(b))
Why is it so??
What is the rational behind this design decision?
Java and C# both use a memory-saving technique called string interning. Because strings are immutable in these languages, they can pool frequently-used strings (included hard-coded string literals, like in your example) and use multiple references to that one string in memory to save space.
As far as I know, in .net the == Operator for Strings is overloaded to use Equals() instead of object identity. See this explanation for details: http://www.dotnetperls.com/string-equals
For if you need to know if it's really the same object, use this:
Object.ReferenceEquals(string1, string2)
Actually, at least in Java, there is a caching mechanism on strings. A pitfall is that two strings that are equal will sometimes, but not always return true when applying the identity operator. the following code prints false:
String a="123";
String b="12";
b=b+"3";
System.out.println(a==b);
If you really want to make sure, that a.equals(b) == true but (a==b) == false evaluates to false for two String a and b, then you can use the completely undervalued (^^) String constructor:
String a = new String("abc");
String b = new String("abc");
if (a.equals(b)) {
doTheyAreEqual();
if (a != b) {
doButNotTheSame();
}
}

Categories

Resources