Question

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.

Was it helpful?

Solution

 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top