Here is a blog post by Eric Lippert which answers your question: String interning and String.Empty.
He’s describing similar situation:
object obj = "Int32";
string str1 = "Int32";
string str2 = typeof(int).Name;
Console.WriteLine(obj == str1); // true
Console.WriteLine(str1 == str2); // true
Console.WriteLine(obj == str2); // false !?
So the idea is, that interning does not mean you’ll have only one instance of particular string, even when it’s interned. Only compile time literals are interned by default. It means that following code prints true:
var k1 = "k";
object k2 = "k";
Console.WriteLine(k1 == k2);
But, if you try to create string with "k" content programmatically at runtime, e.g. using string(char[]) constructor, calling ToString() on an object, using StringBuilder, etc, you won’t get interned string by default. This one prints false;
var k1 = "k";
object k2 = new string("k".ToCharArray());
Console.WriteLine(k1 == k2);
Why? Because interning strings at runtime is expensive.
There Ain’t No Such Thing As A Free Lunch.
(…)
In short, it is in the general case not worth it to intern all strings.
And about different behavior with empty string:
Some versions of the .NET runtime automatically intern the empty string at runtime, some do not!