2014-09-05 95 views
9

我想在C#中创建一个通用方法,它将调用基于它的正文中的参数数据类型的不同方法,然后处理它们的结果。我试图通过创建一个通用的包装方法来实现这一点,然后提供处理方法的几个重载 - 包括一个通用的方法,如果没有特定的超载可用的话。C#:通用方法不会调用特定的方法重载

当我直接调用处理方法时,正确选择了适当的版本。但是,当我从包装器方法调用它时,它总是选择通用的,即使对于传递给它的特定数据类型存在匹配的重载。

是否有任何方法来调整代码,使其行为我需要的方式?或者我必须使用不同的方法。

我需要代码与Mono 2.6兼容。

using System; 

class Program 
{ 
    static void Func<T>(T val) 
    { 
     Console.WriteLine("Generic Func"); 
    } 

    static void Func(int val) 
    { 
     Console.WriteLine("Int Func"); 
    } 

    static void Func(string val) 
    { 
     Console.WriteLine("String Func"); 
    } 

    static void FuncWrap<T>(T val) 
    { 
     Console.Write("Wrap: "); 
     Func(val); 
    } 

    static void Main(string[] args) 
    { 
     Func(2); 
     Func("Potato"); 
     Func(2.0); 

     FuncWrap(2); 
     FuncWrap("Potato"); 
     FuncWrap(2.0); 

     Console.Read(); 
    } 
} 
+0

你可以有一个接受int和string的FuncWrap重载(或者直接使用Func方法直接不包装)。 – 2014-09-05 12:20:57

回答

13

有什么办法解决此问题?

根据C#语言规范,它已经是正确的行为。在FuncWrap内调用的Func的过载通常在编译时间确定为,所以它不能根据执行时间类型选择不同的Func过载。改变行为的

的一种方式,但是,使用动态类型:

static void FuncWrap<T>(T val) 
{ 
    Console.Write("Wrap: "); 
    dynamic x = val; 
    Func(x); 
} 

基础上,实际类型的x值在执行时也将立即执行重载解析。这招致了性能成本,但应该做你想做的事情。

或者,你可以在重载的硬编码知识:

static void FuncWrap<T>(T val) 
{ 
    Console.Write("Wrap: "); 
    if (typeof(T) == typeof(string)) 
    { 
     Func((string)(object)val); 
    } 
    else if (typeof(T) == typeof(int)) 
    { 
     Func((int)(object)val); 
    } 
    else 
    { 
     Func(val); 
    } 
} 

这显然很可怕,但。

+0

对不起,我没有正确地说出来。我的意思是“正确的”,因为它会按照我需要的方式行事。 动态似乎不适用于Mono 2.6(我在Unity引擎中使用代码)。 是的,第二种方法是不可取的,我正在寻找更干净的东西(并且理想的更快)。 – 2014-09-05 12:10:33

+0

@TomFrooxiusMariank:查看Mono 2.6的发行说明,应*支持*它可能是Unity实际上限制了一些旧的配置文件。 (它需要.NET 4配置文件。)如果没有'dynamic',你可能会在我的答案结束时使用黑客最好的解决方案......这样做表现会相当好(比动态更好,这基本上是使用反射)。你当然可以使用反射,但这不会很快。如果这些都不合适,你应该考虑重新设计。 – 2014-09-05 12:13:49

+0

我明白了,我现在可能不太会用目前的Unity版本的Unity,但我会检查是否可以以某种方式更改配置文件,但我不确定这是否会导致不希望的后果。 如果它不起作用,我可能会重新编写代码以避免使用此功能。 感谢您的帮助。 – 2014-09-05 12:17:46