【问题标题】:c# overload error for generic typec#泛型类型的重载错误
【发布时间】:2012-12-09 14:10:10
【问题描述】:

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

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&lt;int&gt; 调用 Helper.Can(Object o) 而不是 Helper.Can(int i)?

【问题讨论】:

    标签: c# generics overloading


    【解决方案1】:

    这样不行。

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

    【讨论】:

    • 我不太同意“泛型类型参数在运行时解析”的说法。如果是这种情况,编译器无法在编译时告诉您无法从 List&lt;string&gt; 获取 int 项。 被认为是在编译时未解决的是泛型类中泛型类型参数的出现。
    • @O.R.Mapper:我的意思是在泛型类中。
    【解决方案2】:

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

    class My<T>
    {
       public static bool can = CanWithDynamic();
    
       private static bool CanWithDynamic() {
          dynamic runtimeT = default(T);
          return Helper.Can(runtimeT);
     }
    

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

    【讨论】:

      【解决方案3】:

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

      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
      

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

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

      【讨论】:

        猜你喜欢
        • 2019-06-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多