我是C#的新手,并试图在周末写一个SNTP服务器。 在这个开发过程中,我最终遇到了与此问题完全相同的问题:How to use generics to pass argument to a non-generic method?
这里重复的问题是:"如何使用泛型将参数传递给非泛型方法?"这个问题的关键答案是,所讨论的非泛型方法没有接受对象的重载。
现在我的问题是一个后续问题:为什么泛型实现了这种方式?或者重新说一下,为什么需要约束?
到目前为止,我的理解是泛型有助于保持编译时类型安全性,这意味着编译器知道在编译时处理什么类型。
为什么C#(或者这个问题应该与CLR有关)实现,以便编译器可以接受这样一个事实:正在创建一个通用的类/方法,其中可以提供一个可能不是的参数在所有情况下均可接受然后,当调用泛型类/方法时,编译器可以看到问题并在那时抱怨 。
这是技术限制吗?
似乎真的很遗憾,无法创建泛型方法来包装具有多个重载的非泛型方法。除非我选择将类型检查推迟到上述问题的解决方案的运行时间,否则我必须用一套方法包装这个重载方法,每个签名一个,即使其中的代码看起来相同。这将是利用通用方法的理想场所。
答案 0 :(得分:2)
能够最好地解释这一点的人是Eric Lippert,他在What’s the difference, part one: Generics are not templates做了:
我们执行重载决策一次并烘焙结果。当某人(可能在完全不同的程序集中)使用字符串作为方法的类型参数时,我们不会在运行时更改它。我们为泛型类型生成的IL已经有了它要调用的方法。抖动并没有说“好吧,我碰巧知道如果我们要求C#编译器立即执行此附加信息,那么它会选择不同的重载。让我重写生成的代码,忽略C#编译器最初生成的代码......“抖动对C#的规则一无所知。
[...]
现在,如果您确实希望在运行时根据参数的运行时类型重新执行重载决策,我们可以为您执行此操作;这就是新的“动态”功能在C#4.0中的作用。只需将“object”替换为“dynamic”,当你进行涉及该对象的调用时,我们将在运行时运行重载决策算法并动态吐出调用编译器可能选择的方法的代码,让它知道所有运行时编译时的类型。
为什么不呢:因为运行时不知道如何重新生成所需的代码。
关于设计理念的一些事情,你的代码应该尽早失败,最好是在编译期间,但我现在找不到这个引用。