Consider the following:
using System;
using System.Dynamic;
using System.Linq;
namespace DynamicObjectTest
{
class Program
{
static void Main(string[] args)
{
dynamic dyn = new TestDynamic();
Console.ReadKey();
foreach (var i in Enumerable.Range(0, 100))
{
Console.WriteLine(dyn.Foo());
Console.WriteLine(dyn.Bar());
}
Console.ReadKey();
}
}
class TestDynamic : DynamicObject
{
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
if (binder.Name == "Foo")
{
result = "Bar";
return true;
}
else if (binder.Name == "Bar")
{
result = "Foo";
return true;
}
return base.TryInvokeMember(binder, args, out result);
}
}
}
When running this program, four exceptions of type RuntimeBinderException
are thrown. You can observe this either by breaking on all thrown exceptions (Debug/Exceptions.../check the Common Language Runtime Exceptions Throw checkbox) or by using perfmon:
Now these exceptions are obviously caught and handled internally because the TryInvokeMember
method is called afterwards. However, it seems heavy-handed and an inappropriate use of exceptions if you subscribe to the "use exceptions only in exceptional circumstances" mantra. For my specific example it's not really a problem because the same members - Foo
and Bar
- are repeatedly invoked. However, I have other scenarios in mind where the members are far less static.
Is there anything that can be done to help the runtime invoke TryInvokeMember
without throwing any exceptions?
The system sometimes throws and catches exceptions internally. There is nothing you can do (except submit feedback to http://connect.microsoft.com/VisualStudio but there is no basis since this is unlikely to affect performance -- other overhead related to DynamicObject
greatly exceeds this).
(If I had to guess, internally this might be like the memory "page fault" hardware exception: the system allows the exception to occur, then catches it and brings things together so that the future execution succeeds. This technique can be extremely efficient since it makes use of the CPU's exception features so that no conditional branching is needed in the code.)
NOTE: To try out the code in the original post, be sure to turn off the "Just My Code" option as well as configuring to break on all thrown exceptions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With