What is the difference between calling a delegate directly, using DynamicInvoke, and using DynamicInvokeImpl?

后端 未结 3 757
心在旅途
心在旅途 2020-12-14 01:36

The docs for both DynamicInvoke and DynamicInvokeImpl say:

Dynamically invokes (late-bound) the method represented by the current delegate.

3条回答
  •  伪装坚强ぢ
    2020-12-14 02:09

    Coincidentally I have found another difference.

    If Invoke throws an exception it can be caught by the expected exception type. However DynamicInvoke throws a TargetInvokationException. Here is a small demo:

    using System;
    using System.Collections.Generic;
    
    namespace DynamicInvokeVsInvoke
    {
       public class StrategiesProvider
       {
          private readonly Dictionary strategies;
    
          public StrategiesProvider()
          {
             strategies = new Dictionary
                          {
                             {StrategyTypes.NoWay, () => { throw new NotSupportedException(); }}
                             // more strategies...
                          };
          }
    
          public void CallStrategyWithDynamicInvoke(StrategyTypes strategyType)
          {
             strategies[strategyType].DynamicInvoke();
          }
    
          public void CallStrategyWithInvoke(StrategyTypes strategyType)
          {
             strategies[strategyType].Invoke();
          }
       }
    
       public enum StrategyTypes
       {
          NoWay = 0,
          ThisWay,
          ThatWay
       }
    }
    

    While the second test goes green, the first one faces a TargetInvokationException.

    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using SharpTestsEx;
    
    namespace DynamicInvokeVsInvoke.Tests
    {
       [TestClass]
       public class DynamicInvokeVsInvokeTests
       {
          [TestMethod]
          public void Call_strategy_with_dynamic_invoke_can_be_catched()
          {
             bool catched = false;
             try
             {
                new StrategiesProvider().CallStrategyWithDynamicInvoke(StrategyTypes.NoWay);
             }
             catch(NotSupportedException exc)
             {
                /* Fails because the NotSupportedException is wrapped
                 * inside a TargetInvokationException! */
                catched = true;
             }
             catched.Should().Be(true);
          }
    
          [TestMethod]
          public void Call_strategy_with_invoke_can_be_catched()
          {
             bool catched = false;
             try
             {
                new StrategiesProvider().CallStrategyWithInvoke(StrategyTypes.NoWay);
             }
             catch(NotSupportedException exc)
             {
                catched = true;
             }
             catched.Should().Be(true);
          }
       }
    }
    

提交回复
热议问题