2

Why the quick watch shows the statement p == "" as false, but we are going in the if statement.

    static void Main(string[] args)
    {
        string q = "";

        A(q);
    }

    static void A (object p)
    {
        if(p == null || p =="")
        {
            Console.WriteLine("Debugger shows false");
        }
    }

Is it a bug ?

Note that according to Compare string and object in c# p == "" should still evaluate to true as "" is an interned string - which indeed happens when code is executed, but fails in quick watch.

enter image description here

Community
  • 1
  • 1
mybirthname
  • 17,949
  • 3
  • 31
  • 55

3 Answers3

4

Since p is declared as an object it is using reference equality, not value equality. The problem is that the compiler will "intern" string literals to save memory, so when you do

string q = ""

the compiler uses a reference to an interned string in memory. Later when you do

if(p == "")

The compiler has already interned the string, and uses the same reference,so reference equality returns true here as well.

The interned string reference is not being used by the QuickWatch window, so the reference p and the string "" are different references, and the statement evaluates to false.

The proper was to compare string values is to use Equals which is overridden and will always use value equality:

if(p == null || p.Equals(""))  // should evaluate to "true" in both places.

or just

if(string.IsNullOrEmpty(p))

The compiler is warning you of this common mistake; if you hover over the green underline in the IDE you will see the warning message.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • Agreed, it has to be a bug in the Quick Watch tool – chomba May 21 '16 at 01:53
  • @chomba No, the _proper_ way to compare strings is to use `Equals`. It's a bug in the program that luckily returns the expected result. – D Stanley May 21 '16 at 01:54
  • I see, so it's a limitation of the QuickWatch tool in a sense that it can't be aware of the memory optimization the runtime will perform right? – chomba May 21 '16 at 02:04
  • 1
    Here is a great article by Eric Lippert of the C# team on this subject https://blogs.msdn.microsoft.com/ericlippert/2009/09/28/string-interning-and-string-empty/ – BateTech May 21 '16 at 03:01
  • @chomba No, it's highlighting the problem that you are comparing strings by reference equality. You should never _rely_ on string interning since it's a runtime optimization and in not a guarantee. Use value comparison methods instead and you'll get proper behavior in all places. – D Stanley May 22 '16 at 02:26
2

Here's a link to the string class:

https://msdn.microsoft.com/en-us/library/362314fe.aspx

object and string are both reference types, but string treats equality operators differently as mentioned in the link.

Also, I use string.IsNullOrEmpty(string) to check if a string is null or empty.

Bill
  • 125
  • 4
  • p == " " is false. You're comparing the reference of p to the reference of an empty string. – Bill May 21 '16 at 01:43
  • You're comparing an empty string against an object, not another string. You need to cast the object to a string, so it'll do a string comparison and not a reference comparison. It's explained in the link I pasted. – Bill May 21 '16 at 01:47
  • You are right; the problem is that the string is _interned_, so in the compiled program they are the same reference, but not in the QuickWatch window. – D Stanley May 21 '16 at 01:52
0

i think you can use

(string.IsNullOrEmpty(p.ToString()))
Cuong Ngo
  • 76
  • 3
  • i think p is object . And you convert to string p.ToString(); you're comparing object with string is "" .You can't compare object with string – Cuong Ngo May 21 '16 at 01:46