传递generics参数会导致调用错误的重载

我正在尝试更新Medusa以允许在目前使用List任何地方使用装饰的POCO。 我遇到的问题是调用了错误的重载。 这是我所看到的一个简单例子:

 void Run() { CallDoSomething("Hello World", new object()); CallDoSomething("Hello World2", new List()); } // `DoSomething` represents the functions that do the heavy lifting public T DoSomething(string someString, List ints) where T : class { Console.WriteLine("List: {0}", someString); return default(T); } public T DoSomething(string someString, object ints) where T : class { Console.WriteLine("object: {0}", someString); // In my real implementation, this turns the object to a typed List // and passes it to the previous overload. return default(T); } // We're trying to refactor the code in this method to reduce code duplication in // the `CallDoSomething` methods that will actually be called by the end user internal T CallDoSomething(string someString, U ints) where T : class { // Do a bunch of stuff here that would otherwise be duplicated by the `CallDoSomething` methods return DoSomething(someString, ints); } public T CallDoSomething(string someString, List ints) where T : class { return CallDoSomething<T, List>(someString, ints); } public T CallDoSomething(string someString, object ints) where T : class { return CallDoSomething(someString, ints); } 

在这种情况下,结果输出是:

 object: Hello World object: Hello World2 

虽然我期待它是:

 object: Hello World List: HelloWorld2 

有意义的是,两个案例都是针对带有object参数的重载,因为它们都是对象。 我怀疑这种情况正在发生,因为(据我所知)generics和重载解析是在编译时而不是运行时处理的。

我遇到的第一个选择是使用Reflection在CallDoSomething动态调用调用,但这感觉太脏了。 相反,我提出的解决方案涉及将委托传递给CallDoSomething ,这似乎有效。 这是它的样子:

 void Run() { CallDoSomething("Hello World", new object()); CallDoSomething("Hello World2", new List()); } public T DoSomething(string someString, List ints) where T : class { Console.WriteLine("List: {0}", someString); return default(T); } public T DoSomething(string someString, object ints) where T : class { Console.WriteLine("object: {0}", someString); return default(T); } internal delegate T DoSomethingDelegate(string someString, U ints) where T : class; internal T CallDoSomething(string someString, U ints, DoSomethingDelegate doSomething) where T : class { // Do a bunch of stuff here that would otherwise be duplicated by the `CallDoSomething` methods return doSomething(someString, ints); } public T CallDoSomething(string someString, List ints) where T : class { return CallDoSomething<T, List>(someString, ints, DoSomething); } public T CallDoSomething(string someString, object ints) where T : class { return CallDoSomething(someString, ints, DoSomething); } 

这似乎工作,它删除了大量的代码重复,但它使代码相当复杂。 有没有更好的方法来解决这个问题?

是的,重载在编译时解决。 如果您正在使用C#4, 可以强制在执行时对其进行评估,如下所示:

 internal T CallDoSomething(string someString, U ints) where T : class { dynamic d = ints; return DoSomething(someString, d); } 

但是,如果可能的话,我个人会尝试简化您的设计。 这种事情很快变得混乱。