传递错误的超负荷泛型参数结果被称为 [英] Passing generic parameter results in wrong overload being called

查看:111
本文介绍了传递错误的超负荷泛型参数结果被称为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图更新美杜莎允许装饰中使用波苏斯任何地方目前使用列表与LT;&的DbParameter GT; 。我遇到的问题是错误的超载被调用。以下是我看到的一个简单的例子:

I'm trying to update Medusa to allow decorated POCOs to be used anywhere it currently uses List<DbParameter>. The problem I'm running into is that the wrong overload is being called. Here is a simple example of what I'm seeing:

void Run()
{
    CallDoSomething<Program>("Hello World", new object());
    CallDoSomething<Program>("Hello World2", new List<int>());
}

// `DoSomething<T>` represents the functions that do the heavy lifting
public T DoSomething<T>(string someString, List<int> ints) where T : class
{
    Console.WriteLine("List<int>: {0}", someString);
    return default(T);
}
public T DoSomething<T>(string someString, object ints) where T : class
{
    Console.WriteLine("object: {0}", someString);
    // In my real implementation, this turns the object to a typed List<T>
    // 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<T>` methods that will actually be called by the end user
internal T CallDoSomething<T, U>(string someString, U ints) where T : class
{
    // Do a bunch of stuff here that would otherwise be duplicated by the `CallDoSomething<T>` methods
    return DoSomething<T>(someString, ints);
}

public T CallDoSomething<T>(string someString, List<int> ints) where T : class
{
    return CallDoSomething<T, List<int>>(someString, ints);
}
public T CallDoSomething<T>(string someString, object ints) where T : class
{
    return CallDoSomething<T, object>(someString, ints);
}

在这种情况下,所得到的输出是:

In this case, the resulting output is:

object: Hello World
object: Hello World2

虽然我希望它是:

object: Hello World
List<int>: HelloWorld2

它种是有道理的,这两种情况都是针对超载服用对象参数,因为他们两人都是对象。我怀疑这是因为发生的事情(据我所知)泛型和重载决议在编译时,而不是运行时的处理方式。

It kind of makes sense that both cases were directed to the overload taking an object parameter since both of them are objects. I suspect this is happening because (from what I know) Generics and overload resolution are handled at compile time rather than runtime.

这来找我的第一选择是使用反射动态调用呼叫 CallDoSomething< T,U> ,但觉得太脏了。相反,我拿出解决方案涉及到传递一个委托 CallDoSomething< T,U> 这似乎工作。这里是什么样子:

The first alternative that came to me was to use Reflection to invoke the call dynamically in CallDoSomething<T, U>, but that felt too dirty. Instead the solution I've come up with involves passing a delegate to CallDoSomething<T, U> which seems to work. Here's what it looks like:

void Run()
{
    CallDoSomething<Program>("Hello World", new object());
    CallDoSomething<Program>("Hello World2", new List<int>());
}

public T DoSomething<T>(string someString, List<int> ints) where T : class
{
    Console.WriteLine("List<int>: {0}", someString);
    return default(T);
}
public T DoSomething<T>(string someString, object ints) where T : class
{
    Console.WriteLine("object: {0}", someString);
    return default(T);
}

internal delegate T DoSomethingDelegate<T, U>(string someString, U ints) where T : class;
internal T CallDoSomething<T, U>(string someString, U ints, DoSomethingDelegate<T, U> doSomething) where T : class
{
    // Do a bunch of stuff here that would otherwise be duplicated by the `CallDoSomething<T>` methods
    return doSomething(someString, ints);
}

public T CallDoSomething<T>(string someString, List<int> ints) where T : class
{
    return CallDoSomething<T, List<int>>(someString, ints, DoSomething<T>);
}
public T CallDoSomething<T>(string someString, object ints) where T : class
{
    return CallDoSomething<T, object>(someString, ints, DoSomething<T>);
}

这似乎工作并删除了大量的重复代码,但它使得代码相当费解。有没有更好的方式来处理这个问题呢?

This seems to work and it removes a large amount of code duplication, but it makes the code fairly convoluted. Is there a better way to approach this problem?

推荐答案

是的,过载在编译时解决。您的可以的迫使它在执行时,如果你正在使用C#4进行评估,如:

Yes, the overload is resolved at compile-time. You can force it to be evaluated at execution time if you're using C# 4, like this:

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



不过,我个人倒尝试,如果你可能可以简化您的设计。这样的事情就会变得混乱的非常的快。

这篇关于传递错误的超负荷泛型参数结果被称为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆