with - instantiate delegate c#




Qual è la differenza tra chiamare direttamente un delegato, utilizzare DynamicInvoke e utilizzare DynamicInvokeImpl? (2)

Davvero non c'è alcuna differenza funzionale tra i due. se si avvia l'implementazione in reflector, si noterà che DynamicInvoke chiama semplicemente DynamicInvokeImpl con lo stesso insieme di argomenti. Non viene eseguita alcuna convalida aggiuntiva ed è un metodo non virtuale, quindi non vi è alcuna possibilità che il comportamento venga modificato da una classe derivata. DynamicInvokeImpl è un metodo virtuale in cui viene eseguito tutto il lavoro effettivo.

I documenti per DynamicInvoke e DynamicInvokeImpl dicono:

Richiama dinamicamente (late-bound) il metodo rappresentato dal delegato corrente.

Ho notato che DynamicInvoke e DynamicInvokeImpl accettano una matrice di oggetti invece di un elenco specifico di argomenti (che è la parte in ritardo che indovinerei). Ma è questa l'unica differenza? E qual è la differenza tra DynamicInvoke e DynamicInvokeImpl.


Per coincidenza ho trovato un'altra differenza.

Se Invoke genera un'eccezione, può essere catturato dal tipo di eccezione previsto. Tuttavia, DynamicInvoke genera una TargetInvokationException . Ecco una piccola demo:

using System;
using System.Collections.Generic;

namespace DynamicInvokeVsInvoke
{
   public class StrategiesProvider
   {
      private readonly Dictionary<StrategyTypes, Action> strategies;

      public StrategiesProvider()
      {
         strategies = new Dictionary<StrategyTypes, Action>
                      {
                         {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
   }
}

Mentre il secondo test diventa verde, il primo affronta una 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);
      }
   }
}




delegates