What you are describing is correct behaviour.
The definition of ==
in Object
compares the references of its arguments. This is different from the implementation of ==
for String
which compares the values of the strings. Operators in C# are not virtual. This means that even though your objects are actually strings, because the static type is object
the ==
from Object
is called, meaning a reference comparison will be made.
In C# strings can be interned in the intern pool. Normally when you create new strings at runtime you receive a reference to a completely new string object. To get an interned string you can call the string.Intern method. However when you compile C# code, the literal strings are interned automatically for you so if you have the same literal string in two places in your code you will get a reference to the same string object.
In the immediate window the strings are apparently not interned - new strings are created each time even if they have the same value. But there is no requirement in .NET that all strings must be interned, so I do not consider this to be a bug.
Your code should avoid relying on whether or not strings are interned as this is an implementation detail.