According to the documentation for TryBinaryOperation this method will be called when the left hand side of a binary operation is a dynamic object.
I've got a class that derives from dynamic object and am seeing that doesn't always seem to be the case. For this example I would expect 3 calls to my override TryBinaryOperation
but only get 2.
public class MyDynamic : DynamicObject
{
public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
{
Console.WriteLine("operation = " + binder.Operation.ToString());
result = arg;
return true;
}
}
class Program
{
static void Main(string[] args)
{
dynamic d = new MyDynamic();
dynamic d1 = d + "add it";
dynamic d2 = d + 1;
dynamic d3 = d >> "shift it";
Console.WriteLine("");
Console.WriteLine(d1);
Console.WriteLine(d2);
Console.WriteLine(d3);
}
}
The first invocation however returns the string "DynamicRestProxy.UnitTests.MyDynamicadd it
"; i.e. d.ToString() + "add it"
is being called by the addition operator instead of trying the binary operation of my dynamic class. Further if the right hand operator of "+" is an int the dynamic operation is attempted.
The output of the above program is (notice that the call d + "add it"
does not get to TryBinaryOperation
):
operation = Add
operation = RightShift
DynamicRestProxy.UnitTests.MyDynamicadd it
1
shift it
where I would expect it to be
operation = Add
operation = Add
operation = RightShift
add it
1
shift it
Is this correct expected behavior? If so is there any more documentation somewhere that would explain?
This is using VS.NET 2013 and .NET 4.5.
dynamic d1 = d + "add it";
That's not a binary operation, that's string concatenation. Documented in the MSDN article for DynamicObject.TryBinaryOperation(), the Add operation has this description:
An addition operation without overflow checking, for numeric operands.
The binder already knows how to concatenate strings. All that's required is to get your DynamicObject converted to a string. Which you can see by adding the ToString() override:
public override string ToString() {
return base.ToString();
}
Set a breakpoint on it and look at the call stack when it breaks:
ConsoleApplication327.exe!ConsoleApplication327.MyDynamic.ToString() Line 22 C# mscorlib.dll!string.Concat(object arg0, object arg1) + 0x1e bytes
System.Core.dll!System.Dynamic.UpdateDelegates.UpdateAndExecute2(System.Runtime.CompilerServices.CallSite site, object arg0, string arg1) + 0x2ae bytes
ConsoleApplication327.exe!ConsoleApplication327.Program.Main(string[] args) Line 30 + 0x146 bytes C#
Line #30 is the d1
assignment statement in my test program.