Why does string concatenation with the + operator work with dynamic types in C#?

c# dynamic dynamic-language-runtime expression-trees string

Question

I recently saw an example where the following was demonstrated to work:

T Add<T>(dynamic a, dynamic b)
{
    return a + b;
}

Add<string>("hello", "world");  // Returns "helloworld"

However, if I were to attempt to use expressions to create a "generic" Add function:

ParameterExpression left = Expression.Parameter(typeof(T), "left");
ParameterExpression right = Expression.Parameter(typeof(T), "right");
var add = Expression.Lambda<Func<T, T, T>>(Expression.Add(left, right), left, right).Compile();  // Fails with System.InvalidOperationException : The binary operator Add is not defined for the types 'System.String' and 'System.String' when T == String.

and then used this function with strings, it fails because the String type does not actually implement the + operator, but is simply syntactic sugar for String.Concat().

How then, does dynamic allow this to work? I figured that at runtime it is past the point where + would be rewritten using String.Concat().

Accepted Answer

dynamic uses runtime helper functions that replicate C# compiler rules. One of these rules allows + on string objects even when no operator is defined by the framework. The standard numeric types such as int have no custom operator overload either, that too is done by the compiler and needs to be performed at runtime when using dynamic. This is why you need a reference to Microsoft.CSharp.dll: dynamic cannot work without those helper functions.


Popular Answer

Based on the documentation, maybe instead of Expression.Add(left, right) you could say Expression.Add(left, right, method) where method is the MethodInfo of the static String.Concat(String, String).

var method = typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string), });

EDIT: Hmm, my answer sort of misses the point. The interesting question is: What operations does the runtime consider when it tries to resolve a + that the compiler has let through without type-checking? Bulit-in addition for numeric types? String concatenation? Delegate concatenation? User-defined operator overloads?



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why