Reputation: 439
As I'm checking the following code string s = "a" + 1
works.
In a tooltip Visual Studio shows that it uses string operator + (string left, object right)
Anyway, its not mentioned in the source code of String, as there are only ==
and !=
.
I definitely could assume that it uses something similar to left + right.ToString()
, but really want to check its real source code.
P.S. Having it is not present in the C# source code multiplies my interest to infinity :)
Upvotes: 5
Views: 1271
Reputation: 35115
This is new for me and I'm not a compiler specialist, here's my best shot.
Throughout .NET Compiler Platform ("Roslyn")'s code.
There are 3 built-in operators in c# for string
.
string operator +(string x, string y);
string operator +(string x, object y);
string operator +(object x, string y);
(Reference below)
You can see them in Roslyn's source code in BuiltInOperators
class.
(int)BinaryOperatorKind.StringConcatenation,
(int)BinaryOperatorKind.StringAndObjectConcatenation,
(int)BinaryOperatorKind.ObjectAndStringConcatenation,
The you can follow the Kind
s to the BinaryOperatorKind
enum.
StringConcatenation = String | Addition,
StringAndObjectConcatenation = StringAndObject | Addition,
ObjectAndStringConcatenation = ObjectAndString | Addition,
The end part (after it has been recognized as an addition expression) of the magic of making +
into a call to string.Concat seems to happen in RewriteStringConcatenation
method.
First the left and the right sides are converted to strings, which may require calling ToString()
which you can see in the IL posted by others.
// Convert both sides to a string (calling ToString if necessary)
loweredLeft = ConvertConcatExprToString(syntax, loweredLeft);
loweredRight = ConvertConcatExprToString(syntax, loweredRight);
Many lines after, one of the RewriteStringConcatenationNNNxprs
methods may be called, for example RewriteStringConcatenationTwoExprs
which provides the special string.Concat
method.
private BoundExpression RewriteStringConcatenationTwoExprs(SyntaxNode syntax, BoundExpression loweredLeft, BoundExpression loweredRight)
{
Debug.Assert(loweredLeft.HasAnyErrors || loweredLeft.Type.IsStringType());
Debug.Assert(loweredRight.HasAnyErrors || loweredRight.Type.IsStringType());
var method = UnsafeGetSpecialTypeMethod(syntax, SpecialMember.System_String__ConcatStringString);
Debug.Assert((object)method != null);
return (BoundExpression)BoundCall.Synthesized(syntax, null, method, loweredLeft, loweredRight);
}
The following is from Addition operator section of Expressions article which is part of C# specification.
- String concatenation:
string operator +(string x, string y); string operator +(string x, object y); string operator +(object x, string y);
These overloads of the binary + operator perform string concatenation. 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.
using System; class Test { static void Main() { string s = null; Console.WriteLine("s = >" + s + "<"); // displays s = >< int i = 1; Console.WriteLine("i = " + i); // displays i = 1 float f = 1.2300E+15F; Console.WriteLine("f = " + f); // displays f = 1.23E+15 decimal d = 2.900m; Console.WriteLine("d = " + d); // displays d = 2.900 } }
The result of the string concatenation operator is a string that consists of the characters of the left operand followed by the characters of the right operand. The string concatenation operator never returns a null value. A System.OutOfMemoryException may be thrown if there is not enough memory available to allocate the resulting string.
The source code for .NET 4.8 for string is at here but it only contains sources for operator ==
and operator !=
.
You may or may not find this relevant to this question, but Visual Studio comes with Syntax Visualiser (View -> Other Windows) which provides a window to some of the magic of code generation.
Upvotes: 5
Reputation: 2417
I thought that it call ToString() and String.Concat(string , string)
C#
object aa = 123;
String a = "123" + aa;
IL
.method public hidebysig
instance void DoSomeMoreStuff () cil managed
{
// Method begins at RVA 0x207c
// Code size 33 (0x21)
.maxstack 2
.locals init (
[0] object,
[1] string
)
IL_0000: nop
IL_0001: ldc.i4.s 123
IL_0003: box [System.Private.CoreLib]System.Int32
IL_0008: stloc.0
IL_0009: ldstr "123"
IL_000e: ldloc.0
IL_000f: brtrue.s IL_0014
IL_0011: ldnull
IL_0012: br.s IL_001a
IL_0014: ldloc.0
IL_0015: callvirt instance string [System.Private.CoreLib]System.Object::ToString()
IL_001a: call string [System.Private.CoreLib]System.String::Concat(string, string)
IL_001f: stloc.1
IL_0020: ret
} // end of method SomeClass::DoSomeMoreStuff
Upvotes: 3
Reputation: 11725
It's built into the C# specification. That is why the tooltip show the information it shows, and no additional source code is needed.
Excerpt from Microsoft Doc: + and += operators (C# reference)
The + and += operators are supported by the built-in integral and floating-point numeric types, the string type, and delegate types.
C# is standardized by ECMA International as the ECMA-334 standard and by ISO/IEC as the ISO/IEC 23270 standard. The latest ISO standard ISO/IEC 23270:2018 is available can be downloaded from https://standards.iso.org/ittf/PubliclyAvailableStandards/c075178_ISO_IEC_23270_2018.zip
Excerpt From ISO:
12.9.5 Addition operator For an operation of the form x + y, binary operator overload resolution (§12.4.5) is applied to select a specific operator implementation. The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator
12.4.5 Binary operator overload resolution An operation of the form x op y, where op is an overloadable binary operator, x is an expression of type X, and y is an expression of type Y, is processed as follows:
This list of public available standards listed here: https://standards.iso.org/ittf/PubliclyAvailableStandards/index.html
Upvotes: 2