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);
}
}
}