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 ?
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 ?
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.
+
in string concatenation gets converted into string.Concat
call, which internally calls parameterless ToString
on each object.
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
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.
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
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.
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!