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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top