3

As we know, in C#,

  1. string is a reference type
  2. for string == operator is overloaded so that comparison is performed by value

There is the following variables defined:

string s1 = "foo";
object s2 = "foo";
string s3 = new String(new char[] {'f','o','o'});

bool b1 = (s1==s2); //true
bool b2 = (s2==s3); //false
bool b3 = (s1==s3); //true
bool b4 = (s1.equals(s3)); //true

gettype() for all variables s1, s2, and s3, returned the same val String.

Why is s1==s3 true and s2 == s3 is false? s1 and s2 have the same type - so the == operator should behave the same. As I understand, s1 and s2 also interned. (object.ReferenceEquals(s1, s2) returned True.)

What do I miss?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
lm.
  • 4,033
  • 4
  • 25
  • 37

2 Answers2

5

Why object == string does not match string.operator == (string, string)? Because one of the parameter is not a string... So the next matching one is object.operator == which does not behave as a string comaprison.

Why interned version of the string (s1 and s2) point to the same object? Because it is what interning do - makes sure that same value present only once as an object. In particular it is done for all string constants in same module (at compiler discretion) so both s1 and s2 point to the same and only object that represents "foo" in that assembly.

Why non interned string (s3) is not the same object as (s1/s2)? Because it just not the same - creating strings at run-time does not intern strings.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • Thanks for reply. But if s2 has different type , why s2.GetType() returns string for it ? Is it casted when calling object s2 = "abc" ? – lm. Oct 31 '20 at 06:04
  • 1
    @lm. Type of the object ("string") and type of variable ("object") are two different and almost unrelated things (slightly restricted by type compatibility). Picking what method to execute (including `operator==`) done at compile time based on types of variables / arguments known at compile time which for `s2==s3` is "object==string". – Alexei Levenkov Oct 31 '20 at 06:09
  • 3
    Note that if you force method selection to happen at run-time you get the result you expect - `(dynamic)s2 == s3` returns `true` because when run-time tries to find best match for "string 'some operator ==' string" it will indeed find `string.operator==(string, string)` to be better match than `object.operator==(object,object)`. – Alexei Levenkov Oct 31 '20 at 06:13
1

The == operator (and any operator overloads in C#) are static methods and therefore the invoked operator is choosen by the static types of the arguments. In (s2==s3) the static type of the left hand operand is object and therefore it cannot match the signature of the operator ==(string, string) method.

Try s2.Equals(s3) instead. Equals is a virtual function and therefore operates on the dynamic type of s2, which is string. (That's also the reason why s2.GetType() returns string).

PMF
  • 14,535
  • 3
  • 23
  • 49