Preparing .NET Interview - Part Five (Equality)

Here are the links to previous articles:

I am here to continue my series related to .NET interview preparation. Today, we will discuss the questions related to equality and go through the answers in an easy way.

So let’s take questions one by one.

Question: How does equality operator == work with value and reference types? Explain with example.

Answer:

== is the comparison operator that compares reference identity of reference types (except string) and data of value types. For string type, it always checks the content.

Compiler overloads == is based on the compile time type of the operands. For example if == is used in object type operands, it will resolve to System.Object.ReferenceEqualsin runtime.

Example:

  1. //Value types and string - Compares data or content.  
  2. Console.WriteLine("-------------------Value Types and string:-------------------");  
  3. Console.WriteLine("Compare {0} and {1}: {2}", 2, 2, 2 == 2); //True, Uses int.operator  
  4. Console.WriteLine("Compare {0} and 2.0: {1}", 2, 2 == 2.0); //True, Uses double.operator  
  5. Console.WriteLine("Compare {0} and {1}: {2}", 2, 3, 2 == 3); //False, Uses int.operator  
  6. Console.WriteLine("Compare {0} and {1}: {2}""prakash""prakash""prakash" == "prakash"); //True, Uses string.operator  
  7. Console.WriteLine("Compare {0} and {1}: {2}""prakash""prakash""prakash" == newstring("prakash".ToCharArray())); //True, Uses string.operator  
  8. Console.WriteLine("Compare {0} and {1}: {2}""prakash""tripathi""prakash" == "tripathi"); //False, Uses string.operator  
  9.   
  10. ////Reference types - Compares reference  
  11. Console.WriteLine("\n-------------------Reference Types:-------------------");  
  12. objectobj1 = "prakash";  
  13. objectobj2 = newstring("prakash".ToCharArray());  
  14. Console.WriteLine("Compare {0} and {1}: {2}", obj1, obj2, obj1 == obj2); //False, Uses object.operator and compares reference  
Output

see output

As you can see that for value types and string, == has usesdoverloaded version (int.operator, double.operator and string.operator) and compared the data or content whereas for reference type (i.e. object) it has used object.operator and compared the reference.

Question: What is Equals method and how is it  different from ==? Explain with example.

Answer

Equalsis  used to compare the data equality for instances of the same type unlike == which checks the references (of reference types). Equals is a virtual method and resolves at runtime (unlike ==).

For string types, Equals use its string overload to compare the content of the string. Additionally, if any object type gets resolved as string at runtime then it compares the string content instead of reference.

The following example clearly illustrates the difference of == and Equals where for two object type variables (obj1, obj2), both are used.
  1. object obj1 = "prakash";  
  2. object obj2 = newstring("prakash".ToCharArray());  
  3. Console.WriteLine("Compare {0} and {1}: {2}", obj1, obj2, obj1 == obj2); //False, Uses object.operator and compares reference   
  4. Console.WriteLine("Compare {0} and {1}: {2}", obj1, obj2, obj1.Equals(obj2)); //True, Compares content of string.   
Output

see result

As you can see that == compared the references of obj1 and obj2 whereas Equals just checked the data or content.

Question: What’s the ReferenceEquals method and how is it different from == and Equals?

Answer

ReferenceEquals is a static method that checks if the two objects are of same instance or not unlike Equals that checks the data equality and == which behaves differently for value and reference types.

For value type comparisons, ReferenceEquals always returns false because before checking, it boxes the values and due to that a different object instance gets created. For immutable types such as string, ReferenceEquals works in following way-
  • If string content is same and interned (If you don’t know about string interning, follow Que. 4 below) in two string instances, ReferenceEquals returns true.

  • If string is not interned, ReferenceEquals will return false despite whether the content is matching.

Example:

  1. Console.WriteLine("-------------------Value Types and string:-------------------");  
  2. Console.WriteLine("Compare {0} and {1} using ReferenceEquals: {2}", 2, 2, object.ReferenceEquals(2, 2)); //False, for value types, ReferenceEquals always returns false.   
  3. stringname1 = "prakash";  
  4. stringname2 = "prakash";  
  5. stringname3 = newstring("prakash".ToCharArray());  
  6. Console.WriteLine("Compare {0} and {1} using ReferenceEquals: {2}", name1, name2, object.ReferenceEquals(name1, name2)); //True, string is interned  
  7. Console.WriteLine("Compare {0} and {1} using ReferenceEquals: {2}", name1, name3, object.ReferenceEquals(name1, name3)); //False, string is not interned  
  8.   
  9. Console.WriteLine("\n-------------------Reference Types:-------------------");  
  10. objectobj1 = "prakash";  
  11. objectobj2 = newstring("prakash".ToCharArray());  
  12. objectobj3 = obj1;  
  13. Console.WriteLine("Compare {0} and {1} using ReferenceEquals: {2}", obj1, obj2, object.ReferenceEquals(obj1, obj2)); //False, compares references.  
  14. Console.WriteLine("Compare {0} and {1} using ReferenceEquals: {2}", obj1, obj3, object.ReferenceEquals(obj1, obj3)); //True, compares references.  
Output:

Output

As you can see for value types and non-interned strings, ReferenceEquals always returns false and for reference types, instance is compared.

Question: What’s the string interning and when it can be used?

Answer

String interning is low level string pool optimization and can speed up performance when dealing with lot of string comparisons. Any string is called interned if it's present in shared or common string pool also called Interned pool.

When we create string literals, they by default go into intern table or pool. Typically comparisons between two interned or literal strings are faster than a  comparison between interned and dynamically built strings.

String becomes non-interned when we do some sort of manipulation on top of literals however a method (Intern) is provided by .NET Framework to enforce interning manually. Manual interning puts the dynamically built string into intern table and gives the same optimization as literals.

There is one more method (IsInterned) available to check if string is interned or not.

Example:
  1. string str1 = "prakash";  
  2. string str2 = "Hello! ";  
  3. string str3 = str2 + "prakash"//Dynamically added  
  4. Console.WriteLine("Is {0} Interned? {1}", str1, string.IsNullOrEmpty(string.IsInterned(str1)) ? "NO" :"YES");  
  5. Console.WriteLine("Is {0} Interned? {1}", str3, string.IsNullOrEmpty(string.IsInterned(str3)) ? "NO" : "YES");  
Output:

run

As you can see that string literal str1 is interned however dynamically added str3 is not. Also before using Intern in real world applications, have a benchmarking done to know if it’s really giving any significant performance benefit as it may be only useful when dealing with a big load or thousands of string comparisons.

Question: What’s the output of the following program?
  1. Console.WriteLine("{0}", 3.Equals(3.0));  
  2. Console.WriteLine("{0}"object.ReferenceEquals(3, 3.0));  
Answer

False//integer and double comparison
False// ReferenceEquals always returns false for value types

Question: What’s the output of the following program?
  1. string str = null;  
  2. Console.WriteLine("{0}", str == null);  
  3. Console.WriteLine("{0}", str.Equals(null));  
  4. Console.WriteLine("{0}"object.ReferenceEquals(str, null));  
Answer

True//Null comparison is supported
NullReferenceException // Equals doesn’t support null

True//Null comparison is supported

Hope you have liked the article. Look forward for your comments/suggestions.
 
Read more articles on .NET Core: