Operator overloading in common methods

This code snippet refers to C # in depth

static bool AreReferencesEqual<T>(T first, T second) where T : class { return first == second; } static void Main() { string name = "Jon"; string intro1 = "My name is " + name; string intro2 = "My name is " + name; Console.WriteLine(intro1 == intro2); Console.WriteLine(AreReferencesEqual(intro1, intro2)); } 

Output of the above code snippet

 True False 

When the main method is changed to

  static void Main() { string intro1 = "My name is Jon"; string intro2 = "My name is Jon"; Console.WriteLine(intro1 == intro2); Console.WriteLine(AreReferencesEqual(intro1, intro2)); } 

Output of the above code snippet

 True True 

I can’t understand why?

EDIT: Once you understand that line input is not being performed, the following questions do not apply.

How are the parameters obtained in the Generic AreReferencesEqual method in the second code fragment?

What will change the type of a string when it is concatenated to cause the == operator not to call the overloaded Equals method of type String? Strike>

+6
generics c # string-interning
source share
3 answers

In the case of strings, you are probably not going to use reference equality. To access equality and inequality in common methods, it is best to:

 EqualityComparer<T>.Default.Equals(x,y); // for equality Comparer<T>.Default.Compare(x,y); // for inequality 

i.e.

 static bool AreValuesEqual<T>(T first, T second) where T : class { return EqualityComparer<T>.Default.Equals(first,second); } 

It still uses overloaded Equals , but also processes zeros, etc. For inequality, this processes zeros for both IComparable<T> and IComparable .

For other operators, see MiscUtil .


Take the question; when:

  string intro1 = "My name is Jon"; string intro2 = "My name is Jon"; Console.WriteLine(intro1 == intro2); Console.WriteLine(AreReferencesEqual(intro1, intro2)); 

You get true , true because the compiler and runtime are designed to work with strings; any literals you use are interned, and the same instance is used every time in your AppDomain. the compiler (and not the runtime) also concat if possible - i.e.

  string intro1 = "My name is " + "Jon"; string intro2 = "My name is " + "Jon"; Console.WriteLine(intro1 == intro2); Console.WriteLine(AreReferencesEqual(intro1, intro2)); 

is the exact same code as in the previous example. There is no difference. However, if you force it to concatenate strings at run time, it is assumed that they are likely to be short-lived, so they are not interned / reused. So, in the case of:

  string name = "Jon"; string intro1 = "My name is " + name; string intro2 = "My name is " + name; Console.WriteLine(intro1 == intro2); Console.WriteLine(AreReferencesEqual(intro1, intro2)); 

you have 4 lines; “John” (interned), “My Name” (interned), and two different copies from “My Name is John”. Therefore, == returns true, and referential equality returns false. But value-equality ( EqualityComparer<T>.Default ) will still return true.

+13
source share

Learned a new thing today.

I think John said in one of the questions I was trying to answer.

When you create a string using concatenation, == returns true for 2 strings of the same value, but they do not point to the same link (which, as I thought, should be due to string interning. For constants or literals).

In the general version, it calls object.ReferenceEquals (which is different from ==. In the case of a string, == compares the value).

As a result, the concatenated version returns false, while the constant version (literal string) returns true.

EDIT: I think John should be around to explain it a lot better :)
Laziness of me, I bought a book, but have not yet begun it .: (

+5
source share

This has nothing to do with the general method, but instantiating strings

in the first version of main you:

 string name = "Jon"; string intro1 = "My name is " + name; string intro2 = "My name is " + name; 

which creates 4 lines. Two of them are compile-time constants, namely "John" and "My name", however, when initializing intro1 and intro2, the compiler cannot say that the name is always jon and resolves to runtime, creating a new line for each of intro1 and intro2.

in the second version

 string intro1 = "My name is Jon"; string intro2 = "My name is Jon"; 

you only have one line, and this is the compile-time constant: "My name is John", and you assign this line to both intro1 and intro2, and why

 AreReferencesEqual(intro1, intro2) 

returns false in the first case, and true in the second

+2
source share

All Articles