如何以编程方式使用泛型执行重载决策

时间:2012-10-13 17:07:11

标签: c# .net generics overload-resolution

我有许多MethodBase个实例引用了不同的开放式通用方法(expected),例如代表以下方法:

T Foo<T>(T nevermind, T other);
T Foo<T>(string nevermind, T other);

我有一个MethodBase个实例引用实际调用的封闭方法(actual),例如:

int Foo<int>(string nevermind, int other);

我如何以编程方式检查actual封闭方法是否可以匹配任何给定的expected开放方法,尤其是在考虑所有泛型缺陷和并发症时?

具体来说,我想确定给定expected已关闭方法的actual列表中的正确项目是T Foo<T>(string nevermind, T other);,而不是第二个。

此外,对于与MethodBase对应的double Foo<double>(double something, string other),我希望没有匹配的结果。

是否正在迭代候选方法并检查来自expected的每个参数是否可以从相应的actual参数中分配出来?如果是这样,这是最简单的方法吗?我是否需要考虑任何特殊情况,以便不匹配根据.NET中的方法重载解析规则而不会选择的方法?

1 个答案:

答案 0 :(得分:1)

铊;博士。使用反射无法解决问题,至少在我理解的情况下,并且没有更多的特异性。

方法解析规则非常复杂,特别是对于通用方法。你会陷入许多陷阱。您不仅需要知道方法,类型参数,还需要了解有关目标的大量信息以及自己的类型参数。在某些情况下,调用方法。

  • 方法在基类中实现,但被子级隐藏。
  • 方法来自一个接口,并且是显式实现的,并且在实现者身上可能有另一个具有相同名称的方法。
  • Foo<T>(T a, string other)Foo<T>(string a, T other)Foo<T>(string a, string other)等方法以及其他一些变体无法为T = string消除歧义,除非您知道来电的来源(这些是合法的)方法和被调用的方法取决于几个方面。
  • 可以对方法进行通用约束。
  • 参数类型的多态性,包括接口和委托的通用方差。
  • 可选参数。
  • 这种情况一直在继续。

基本上,它永远不会奏效。不使用反射。不是你提出的方式。即使你对可以进行的通话有限制,你也必须决定要检查哪些内容,哪些不可以,你总是会错过一些。这些不是唯一的陷阱,只是随机抽样。

但是,你确实有一些选择。

在我看来,第一个也是最好的选择是退一步思考原始问题。张贴,如果可以的话。它可能有不同的答案,人们将能够更好地为您提供建议。希望理解起来不那么复杂。

如果您极大地限制了问题的范围,例如没有通用约束,没有接口等,这可能是可能的。这很容易出错,因为有很多问题。

您可以尝试使用动态绑定在运行时解析它,但动态绑定解析方法的方式可能与通常的方式不同。不过,我对此并不了解。

您可以挂钩运行时,并在解析时调查方法调用。有这个库。这甚至可以让您了解后期绑定是如何解决的。

最后,您可以查看IL,可能借助各种工具和库,例如Mono.Cecil。在构建的库中,已经执行了方法解析,因此您将确切地看到从哪些位置调用哪些方法。然而,这听起来并不可行。

哦,有Roslyn和其他带接口的编译器。他们已经实现了解析逻辑,因此他们可以使任务更容易。如果它们是开源的,您可以尝试了解如何在那里执行方法解析。不过,我有点不在这里。我怀疑这是不可行的。

我不喜欢发布指向特定库的链接,因为我宁愿你只研究它们。还因为有很多选择。

总结一下,至少在我看来,正如我所理解的那样,没有对方法和更多信息的严格限制,这是不可能的。