6

I have a kind a simple question but I'm surprised.

This code works:

int itemID = 1;
string dirPath = @"C:\" + itemID + @"\abc";

Why don't I have to do itemID.ToString() in this case ?

Miguel-F
  • 13,450
  • 6
  • 38
  • 63
Tony
  • 12,405
  • 36
  • 126
  • 226
  • I think this is an instance of the language adding the toString() conversion for you, since String concatenation is an inherent, non-overridable language feature. There's probably a complete list of situations where it will do it on its own - for instance, I'm reasonably sure passing an int to a String method will not do automatic conversion. – Katana314 Sep 10 '13 at 15:09
  • 4
    possible duplicate of [string = string + int: What's behind the scene? (C#)](http://stackoverflow.com/questions/3398604/string-string-int-whats-behind-the-scene-c) – Kurubaran Sep 10 '13 at 15:12

6 Answers6

13

from MSDN

The binary + operator performs string concatenation when one or both operands are of type string. If an operand of string concatenation is null, an empty string is substituted. Otherwise, any non-string argument is converted to its string representation by invoking the virtual ToString method inherited from type object. If ToString returns null, an empty string is substituted.

Expanding on my answer a bit, based on some comments in other answers...

This process is not merely "Syntactic Sugar" or convenience. It is a result of a core C# language feature called Operator Overloading. In the case of the + Operator and the String + Overload, the Overload is provided as a means to abstract the internals of the String Class, which is a core fundamental of good design principles. The + String Overload provides type safety by ensuring that it never returns a null value, rather returning an empty string for any operand that cannot be converted using the .ToString() method. However, even custom complex types (not just primitives) can be added to a string, assuming that they have a .ToString() overload, without the implementation of the String type knowing any different.

Operator Overloading is a major language feature that more people should learn to harness the power of.

Community
  • 1
  • 1
Claies
  • 22,124
  • 4
  • 53
  • 77
8

+ in string concatenation gets converted into string.Concat call, which internally calls parameterless ToString on each object.

string.Concate Method - MSDN

The method concatenates each object in args by calling the parameterless ToString method of that object; it does not add any delimiters.

EDIT:

Here is what it looks like in ILSpy enter image description here

Habib
  • 219,104
  • 29
  • 407
  • 436
6

The + operator has a number of overloads. Three of them are as follows:

operator + (string a, string b)

operator + (string a, object b)

operator + (object a, string b)

Your code is using the second overload of the operator.

That operator will, after being determined as a match, convert it to a call to string.Concat, which can take any number of objects (of type object) as its parameters.

Within the definition of string.Concat, it will call ToString on all parameters (after null checking them first) to get their string value, and that is what will be concatted.

Because of all of this, you can always concat any object with a string, and it will compile and execute using that object's ToString method.

Community
  • 1
  • 1
Servy
  • 202,030
  • 26
  • 332
  • 449
  • 1
    And of course this explains why the expression must be convertible to `object`, for example `string dirPath = @"C:\" + Math.Abs;` won't compile because 'method group' is not implicitly convertible to `object`. (Then `string dirPath = @"C:\" + (Func)Math.Abs;` compiles but is not useful.) – Jeppe Stig Nielsen Sep 10 '13 at 15:38
  • @Servy, could you please tell where you are seeing operator + overloaded ? I couldn't find it in string.cs – Habib Sep 10 '13 at 19:31
  • @Habib It's a part of the language specs; it's not a user defined operator overload. It's in section 7.8.4 of the C# language specs. – Servy Sep 10 '13 at 19:33
  • +1, thank you. Add that to your answer as well, would be helpful. – Habib Sep 10 '13 at 19:37
1

Because it's done automatically by the compiler.

Basically:

  string a = "abc" + 1; 

is compiled to:

  string a = string.Concat((object)"abc", (object)1);

It's merely syntactic sugar. Although I personally would prefer no automatic conversion.

Reference for Concat: http://msdn.microsoft.com/en-us/library/kbseaaft.aspx

Onur
  • 5,017
  • 5
  • 38
  • 54
  • 2
    The question is, why? – haim770 Sep 10 '13 at 15:08
  • because you concatenate using `+` and having strings next to them that gets cast implicitly – DrCopyPaste Sep 10 '13 at 15:09
  • @haim770 Because platform designers have decided so. :) – Leri Sep 10 '13 at 15:11
  • @Leri, that obvious. still, the question is why didn't they insist on 'type safety' just like they do in other cases. – haim770 Sep 10 '13 at 15:14
  • @haim770 Because unless you are complete idiot, you won't concatenate some random object with string, you will concatenate string representation of object and it's logical. Anyway, this question can only be answered by that person, who made this decision. – Leri Sep 10 '13 at 15:18
  • 1
    @Leri, for me, the question was why `bool a = "1" == 1;` (for example) doesn't compile while `string + int` concatenation does. see other answers to understand why. – haim770 Sep 10 '13 at 15:28
0

This is a language feature. ToString() is called on objects internally when doing string concatenation with the + operator.

The underlying reason for this is mere convenience (and possibly increased readability due to less ToString() calls, but it could also trick you into thinking the object is a string, when in fact it can be anything) for the developer.

For C#, probably Java's behavior was adopted, which is identical. It may be interesting to ask the question why exactly this was introduced in Java in the first place.

tmh
  • 1,385
  • 2
  • 12
  • 18
0

A very interesting question.

Lets look to IL code of your example:

 ldstr     "C:\\"
 ldloc.0
 box       int
 ldstr     "\\abc"
 call      string System.String.Concat(object, object, object)

The called function in behind is System.String.Concat which take 3 objects!

Lets go deeper in .NET source code:

public static String Concat(Object arg0, Object arg1, Object arg2) {
        Contract.Ensures(Contract.Result<String>() != null);
        Contract.EndContractBlock();

        if (arg0 == null)
        { 
            arg0 = String.Empty; 
        }

        if (arg1==null) {
            arg1 = String.Empty;
        }

        if (arg2==null) {
            arg2 = String.Empty; 
        } 
           return Concat(arg0.ToString(), arg1.ToString(), arg2.ToString());
   }  

AS YOU SEE THE ToString() it will be called but later!This is very impressive what the Microsoft guys are doing!

Bassam Alugili
  • 16,345
  • 7
  • 52
  • 70
  • no I just download the .NET source code from :http://www.google.de/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=3&ved=0CEkQFjAC&url=http%3A%2F%2Freferencesource.microsoft.com%2Fnetframework.aspx&ei=B0EvUrCJIcSO4AT6mYD4BQ&usg=AFQjCNEZZp_KW82DQ5GatERyIQF_dNmfQA&sig2=vXZ91FVquE0VR2kVV55MYA&bvm=bv.51773540,d.bGE – Bassam Alugili Sep 10 '13 at 15:56