2

As indicated here, a string that is created at runtime cannot be interned.

However, the following code:

    class Program {
    static void Main(string[] args)
    {
        string s1 = "Programming Is Fun";
        string s3 = s1.ToString();
        Console.WriteLine(Object.ReferenceEquals(s1, s3));
    }
}

gives (VS 2015):

True

So, is it specified somehow which strings are generated in runtime?

BTW:

The code:

using System;
using System.Text;

class Program {
  static void Main(string[] args)
  {
    string s1 = "hop";
    StringBuilder s2 = new StringBuilder(s1);
    string s3 = s2.ToString();
    Console.WriteLine(Object.ReferenceEquals(s1, s3));
  }
}

gives (VS 2015):

False

in opposite to mono (ver. 4.0.2) which gives

True

see the working example.

kuszi
  • 2,069
  • 29
  • 36
  • 2
    `s3` is a variable that references the same string as `s1`, `s1.ToString()` just returns `this`, so it doesn't create a new string. [MSDN](https://msdn.microsoft.com/en-us/library/8tc6ws5s(v=vs.110).aspx). – Tim Schmelter Oct 06 '15 at 14:19
  • 4
    `string.ToString()` does nothing. It return reference to original string. `StringBuilder.ToString()` will generate a string and return its reference. The process of generating may be different and it's maybe simply returning reference to original string if there was no changes to `StringBuilder` in mono. – Sinatr Oct 06 '15 at 14:20
  • Btw. if you remove `pl-pl/` from the MSDN link, everyone will get the version of that article in their (UI)Language. -- (or default to en-US) – Corak Oct 06 '15 at 14:24
  • @Corak thank you (pl-pl) removed. – kuszi Oct 06 '15 at 14:27
  • @Sinatr, Tim Schmelter: This is basically my understanding of how it works, but the main issue is to determine if the execution of such a code depends on compiler optimization and certainly should be avoided or there are some rules I am not aware of. – kuszi Oct 06 '15 at 14:37
  • Why do you use `ReferenceEquals` in first place? `string` has [`Equals`](http://referencesource.microsoft.com/#mscorlib/system/string.cs,372d790ddae4cbb4,references) method (simply use `==`) which compares string in expected way: references first, then lengths, then content. – Sinatr Oct 06 '15 at 14:44
  • @Sinatr Curiosity in the first place. Honestly, I believed that every correct C# program's behavior is well defined, so this is a kind of illumination for me. – kuszi Oct 06 '15 at 14:57
  • `ReferenceEquals` is well-defined. `string.ToString()` is well defined. So you question is basically why [`StringBuilder.ToString()`](http://referencesource.microsoft.com/#mscorlib/system/text/stringbuilder.cs,5a97da49a158a3c9) behave differently in mono? But, does it matter? – Sinatr Oct 06 '15 at 15:05
  • @Sinatr It is likely meaningless, but can be seen as a small scratch on the pure glass :) – kuszi Oct 06 '15 at 15:14
  • @Sinatr Coming back to your previous question, it seems to me that "==" does not compare references. Please have a look at [this code](http://ideone.com/lXXABM) – kuszi Oct 11 '15 at 12:40
  • I don't understand you comment (nor example). Operator `==` from `string` (and I bet from everything) is using `string.Equals()` (overload which doesn't uses `ReferenceEquals` **at all**). [See for yourself](http://referencesource.microsoft.com/#mscorlib/system/string.cs,8281103e6f23cb5c) (use on page search for "operator"). See also [this](http://stackoverflow.com/q/3869601/1997232). – Sinatr Oct 12 '15 at 07:09
  • @Sinatr, I have misunderstood your comment. I was interpreting "comparing references" phrase as "using `ReferenceEquals`". So, you are pretty right, thank you for your patience. – kuszi Oct 12 '15 at 11:15

1 Answers1

5

String.ToString() returns reference to the same string:

public override String ToString() {
    Contract.Ensures(Contract.Result<String>() != null);
    Contract.EndContractBlock();
    return this;
}

And strings created at runtime can be interned. Quote from the MSDN article you referred to:

the runtime does not guarantee that strings created at runtime are interned

Interning is an expensive operation, usually it's too expensive to do it at runtime. If you want to make sure your string is interned, you can use public static String Intern(String str) method.

Jakub Lortz
  • 14,616
  • 3
  • 25
  • 39
  • Thank you. "A string that is created at runtime cannot be interned." is an exact citation from MSDN, so they contradict themselves a little. Anyway, I should read the whole text before asking questions. – kuszi Oct 06 '15 at 14:47
  • 1
    @kuszi MSDN Code sample's comments :)... Text in [the article](https://msdn.microsoft.com/library/dd183759.aspx) says: "... the runtime *does not guarantee* that strings created at runtime are interned, nor does it guarantee that two equal constant strings in different assemblies are interned." – Alexei Levenkov Oct 06 '15 at 14:55
  • 1
    @kuszi possibly comment in the code meant to say "compiler/runtime cannot automatically intern result of concatenation as it requires explicit user request" rather "cannot do that". – Alexei Levenkov Oct 06 '15 at 15:00