如何基于封闭泛型类型调用方法重载?

Ily*_*nov 12 c# generics

假设我有三种方法:

void Foo(MemoryStream v) {Console.WriteLine ("MemoryStream");}
void Foo(Stream v)       {Console.WriteLine ("Stream");}
void Foo(object v)       {Console.WriteLine ("object");}
Run Code Online (Sandbox Code Playgroud)

我调用方法Foo传递开放泛型类型的第一个参数:

void Bar<T>()
{
    Foo(default(T)); //just to show the scenario
    //default(T) or new T() doesn't make a difference, null is irrelevant here
}
Run Code Online (Sandbox Code Playgroud)

我想打电话给MemoryStream超载,所以我关闭泛型类型的方法BarMemoryStream:

Bar<MemoryStream>();
Run Code Online (Sandbox Code Playgroud)

object过度被称为.如果我将通用约束添加到Foo签名where T : Stream,则Stream调用该版本.

有没有办法MemoryStream根据开放泛型类型调度方法调用重载T

我不想使用Delegate.CreateDelegate或其他Reflection API.只是在C#语言的手段.我可能在语言本身内遗漏了一些东西.

尝试使用值类型作为封闭泛型类型并使用静态方法来实现此方案.

Pan*_*vos 9

您描述的内容称为"模板专业化",在C#中不起作用.它在C++中可用,但仍然没有进入C#.

这已在" C#通用接口专业化 "中得到解答.简短的版本就是你不能这样做.您可以解决它强制运行时解析,但在这种情况下使用泛型是没有意义的.泛型应该用于在不同类型上使用相同的代码.

也许还有另一种做你真正想要的方式.我在实现策略或模板方法模式时遇到类似的情况,我希望大多数代码在一般情况下工作,但修改一些特定的步骤.

在这种情况下,最好将自定义步骤作为接口注入到类中,或者甚至在实际创建"模板方法"时将Func <>对象专门化为行为.

当然,还有很多其他方法可以做到这一点,其中一些方法比其他方法更有效

  • 我很喜欢你的回答和Marc的评论.它们为仿制药的使用和使用提供了很好的深入指导.我从来没有纯粹从某种意义上讲它们,相同的功能应用于相同的数据,即使你在msdn和C#的书籍中反复阅读过.我一直认为它们是用开放式的参数化类型或方法,这是泛型原始意图的一个巨大的过度简化 (2认同)

Kri*_*ten 7

这只能使用动态绑定来完成,例如:

void Bar<T>(T value)
{
    dynamic parameter = value;
    Foo(parameter); 
}
Run Code Online (Sandbox Code Playgroud)

请注意,动态分派使用实际运行时对象的实际运行时类型来执行方法分派,因此必须有一个对象.如果值为null,则不起作用.

  • +1.这肯定解决了我的问题.它可以调用正确的重载,而不需要像创建字典或使用案例逻辑这样的丑陋技巧.这是IMO的最佳答案,很遗憾没有选票. (2认同)
  • 到目前为止最佳答案. (2认同)

Ali*_*eza 5

也许是这样的:

void Bar<T>()
{
   if(typeof(T) == typeof(Stream))
      Foo(default(T) as Stream);  //just to show the scenario
}
Run Code Online (Sandbox Code Playgroud)

  • 不知道为什么这被否决了;这不是一个“伟大的”方法,但那是因为场景本身并不理想——它是您对这个问题所能得到的最好的答案。这更多地反映了问题中的代码而不是答案。 (3认同)