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

I recently saw an example where the following was demonstrated:

T Add<T>(dynamic a, dynamic b) { return a + b; } Add<string>("hello", "world"); // Returns "helloworld" 

However, if I tried to use expressions to create a β€œcommon” 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 just the syntactic sugar for String.Concat ().

How then can the dynamics work? I figured that at runtime it goes through the point where + will be rewritten using String.Concat ().

+4
source share
3 answers

dynamic uses run-time helper functions that replicate C # compiler rules. One of these rules allows + on string objects, even if the operator is not defined by the wireframe. Standard numeric types, such as int , do not have a special operator overload, which is also performed by the compiler and must be executed at run time when using dynamic . That is why you need a link to Microsoft.CSharp.dll: dynamic cannot work without these helper functions.

+6
source

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

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

EDIT: Hm, my answer seems to miss. An interesting question: what operations does the runtime perform when trying to solve + , with which the compiler passed the check without type checking? Bulit-in addition for numeric types? String concatenation? Concatenation of delegates? Custom operator overloads?

+3
source

In your first example, a and be are still strings (try this):

 // Define other methods and classes here T Add<T>(dynamic a, dynamic b) { Console.WriteLine(a.GetType()); Console.WriteLine(b.GetType()); return a + b; } 

Maybe that makes sense?

 void Main() { var x = Add<string>(new { val = "hello"},new { val = "world"}); // Returns "hello world" Console.WriteLine(x); } // Define other methods and classes here T Add<T>(dynamic a, dynamic b) { return a.val + b.val; } 
0
source

All Articles