假设我有三种方法:
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超载,所以我关闭泛型类型的方法Bar有MemoryStream:
Bar<MemoryStream>();
Run Code Online (Sandbox Code Playgroud)
但object过度被称为.如果我将通用约束添加到Foo签名where T : Stream,则Stream调用该版本.
有没有办法MemoryStream根据开放泛型类型调度方法调用重载T?
我不想使用Delegate.CreateDelegate或其他Reflection API.只是在C#语言的手段.我可能在语言本身内遗漏了一些东西.
尝试使用值类型作为封闭泛型类型并使用静态方法来实现此方案.
您描述的内容称为"模板专业化",在C#中不起作用.它在C++中可用,但仍然没有进入C#.
这已在" C#通用接口专业化 "中得到解答.简短的版本就是你不能这样做.您可以解决它强制运行时解析,但在这种情况下使用泛型是没有意义的.泛型应该用于在不同类型上使用相同的代码.
也许还有另一种做你真正想要的方式.我在实现策略或模板方法模式时遇到类似的情况,我希望大多数代码在一般情况下工作,但修改一些特定的步骤.
在这种情况下,最好将自定义步骤作为接口注入到类中,或者甚至在实际创建"模板方法"时将Func <>对象专门化为行为.
当然,还有很多其他方法可以做到这一点,其中一些方法比其他方法更有效
这只能使用动态绑定来完成,例如:
void Bar<T>(T value)
{
dynamic parameter = value;
Foo(parameter);
}
Run Code Online (Sandbox Code Playgroud)
请注意,动态分派使用实际运行时对象的实际运行时类型来执行方法分派,因此必须有一个对象.如果值为null,则不起作用.
也许是这样的:
void Bar<T>()
{
if(typeof(T) == typeof(Stream))
Foo(default(T) as Stream); //just to show the scenario
}
Run Code Online (Sandbox Code Playgroud)