【发布时间】:2013-10-21 10:23:35
【问题描述】:
假设我有三种方法:
void Foo(MemoryStream v) {Console.WriteLine ("MemoryStream");}
void Foo(Stream v) {Console.WriteLine ("Stream");}
void Foo(object v) {Console.WriteLine ("object");}
我调用方法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
}
我想调用MemoryStream重载,所以我用MemoryStream关闭泛型方法Bar:
Bar<MemoryStream>();
但是调用了object 重载。如果我将通用约束添加到 Foo 签名 where T : Stream,则调用 Stream 版本。
有没有办法基于开放的泛型类型T 将方法调用分派给MemoryStream 重载?
我不想使用 Delegate.CreateDelegate 或其他反射 API。就在 C# 语言中。我可能在语言本身中遗漏了一些东西。
尝试将值类型作为封闭的泛型类型并使用静态方法来解决此问题。
【问题讨论】:
-
default(T)forMemoryStream是null,所以调用了对象重载。我觉得还可以。 -
@StephaneDelcroix 如果我添加
where T : stream然后default(T)仍然为空,但会调用其他方法。检查 msdn 的过载解决方案。编译器可以猜测表达式的 type,即使结果值为 null。示例Foo((MemoryStream)null)将使用null作为参数调用正确的重载。 -
应该注意,“基于不同的
T做不同的事情”与“泛型”的意图几乎完全相反,后者本质上是定义为“对任何不同的T应用相同的模式” - 泛型 本身 在这里没有帮助你应该不足为奇...... -
您的建议本质上是一个虚拟通话。恐怕唯一的方法是实现自己的 vtable 模式或在 c# 中使用动态调度。
-
顺便说一句,用
new T()替换default(T)仍然调用object重载。这不是关于空值,而是关于泛型和重载!