C# 我可以避免或优化这种动态调用吗?
我正在尝试编写一个类,它可以处理许多不同类型的输入,所有这些输入都实现相同的接口 我有以下代码:C# 我可以避免或优化这种动态调用吗?,c#,generics,optimization,dynamic,C#,Generics,Optimization,Dynamic,我正在尝试编写一个类,它可以处理许多不同类型的输入,所有这些输入都实现相同的接口 我有以下代码: private IEnumerable<IPlan> DevisePlans(ITile tile, IEnumerable<ISpace> spaces) { MethodInfo method = GetType().GetMethod("DevisePlans", Bindi
private IEnumerable<IPlan> DevisePlans(ITile tile, IEnumerable<ISpace> spaces)
{
MethodInfo method = GetType().GetMethod("DevisePlans",
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new[] {tile.GetType(), typeof(ISpace)},
null);
var type = typeof(Func<,,>).MakeGenericType(tile.GetType(), typeof(ISpace), typeof(IEnumerable<IPlan>));
var planner = Delegate.CreateDelegate(type, this, method);
return spaces.SelectMany(s => (IEnumerable<IPlan>)planner.DynamicInvoke(tile, s));
}
这是可行的,但我正在为我的可枚举项的每个迭代调用
DynamicInvoke
。即使我无法完全避免动态调用,是否有任何方法可以优化此方法,使动态调用不再驻留在我的循环中?创建一个表达式树(从expression.call开始),编译它,您将拥有一个快速委托。您应该基于类型缓存委托,这样您就不会多次为同一类型编译。它看起来像是在使用它来调用所提供的平铺的设计计划的最特定重载(而不是覆盖)。假设我的理解是正确的(如果我错了,请一定告诉我),然后只使用动态
-它有一个内置缓存,并为此进行了优化:
return spaces.SelectMany(s =>
(IEnumerable<IPlan>)DevisePlans((dynamic)tile, (dynamic)s)
);
返回空格。选择many(s=>
(IEnumerable)设备计划((动态)平铺,(动态)s)
);
而且。。。就这样
然而,我很想寻找一个涉及多态性(相对于ITile
)或C#4.0方差的答案。认为您在这里寻找的是。为每种类型定义一个带有重载的ITileVisitor接口,然后ITile有一个以访问者为参数的访问方法。它的实现将导致调用正确的design重载。我可以澄清一下:这是什么调用吗?对于更具体的类型,是否有大量的developeplan
重载?或者…?至少可以说,你的代码目标有点模糊。你能概括一下吗?也许还有另一种方法可以剥猫的皮(可以这么说),你不能这样做,除非它是打字;如果是键入的,Delegate.CreateDelegate
(在答案中)已经更直接更快了。您可以编译一个ET,它接受一个对象参数并强制转换为正确的类型。铸造仍然比反射好。这工作非常完美,而且更干净!我需要测试一下它的速度。我在哪里可以找到使用C#4.0方差的解决方案?@Dan关于问题更新/澄清,我认为方差方法不起作用,对不起,为什么要使用(动态)s
?我的代码编译时没有它-这只是为了让ISpace
也使用最具体的重载吗?另外,在SelectMany
中指定类型参数可以避免转换为IEnumerable
@Dan。老实说,这并不重要<代码>动态
具有传染性-如果调用的一部分是动态
(即一个参数),则它们都具有传染性。如果你为了清晰起见想把它去掉,那很好。这似乎不正确。根据是否存在(动态)s
,呼叫的行为会有所不同。(也就是说,如果您有任何依赖于其特定类型的重载函数。)访问者模式要求我修改实现ITile
的类,不幸的是,我不能这样做。否则我会这样做的。
return spaces.SelectMany(s =>
(IEnumerable<IPlan>)DevisePlans((dynamic)tile, (dynamic)s)
);