6

我想根据不同的泛型类型使用方法重载来获得不同的结果。这没用。我的代码清楚地显示了它。

static class Helper
{

    public static bool Can(int i)
    {
        return true;
    }

    public static bool Can(Object o)
    {
        return false;
    }
}

class My<T>
{
    public static bool can = Helper.Can(default(T));
}

Console.WriteLine(Helper.Can(default(int)));//True,it is OK

Console.WriteLine(My<int>.can);//false?? why the overload doesn't work
Console.WriteLine(My<Object>.can);//false

为什么My<int>调用 Helper.Can(Object o) 而不是 Helper.Can(int i)?

4

3 回答 3

4

它不是那样工作的。

重载完全在编译时解决;泛型类型参数在运行时解析。由于编译器不
知道,您的代码将始终调用.TintCan(Object)

于 2012-12-09T14:11:32.940 回答
3

通常,它会在编译时解析为 Object,但您可以使用dynamic关键字告诉它等到运行时:

class My<T>
{
   public static bool can = CanWithDynamic();

   private static bool CanWithDynamic() {
      dynamic runtimeT = default(T);
      return Helper.Can(runtimeT);
 }

因此,这将适用于您正在尝试做的事情,并且将调用正确的重载。但是,与在运行时解决的任何问题一样,都会产生与之相关的性能成本。可能不多,但是如果您经常调用此方法,它可能会产生影响。

于 2012-12-09T14:27:06.480 回答
1

它有点冗长,但你可以通过使用反射来实现你想要的:

class My<T>
{
    static bool doStuff()
    {
        var rightMehod = typeof(Helper).GetMethods().Where(p =>
            {
                if (!p.Name.Equals("Can"))
                    return false;

                if (!p.ReturnType.Equals(typeof(bool)))
                    return false;

                if (p.GetParameters().Length != 1)
                    return false;

                var par = p.GetParameters().First();
                return par.ParameterType.Equals(typeof(T));
            }).FirstOrDefault();

        if (rightMehod == null)
        {
            return Helper.Can(default(T));
        }
        else
        {
            return (bool)rightMehod.Invoke(null, new object[] { default(T) });
        }
    }

    public static bool can = doStuff();
}

这边走,

My<string>.can == false
My<int>.can == true
My<object>.can == false

当然,通过一些额外的技巧(和泛型类型的使用),您将能够在许多不同的情况下广泛地重用该片段。

补充一点:在这个例子中,我对你的具体例子使用了直接类型比较。请注意,在处理继承类型时,这将无法正常工作(当然,还有一些额外的歧义:)。

于 2012-12-09T14:23:26.537 回答