使用T类型参数调用泛型方法

时间:2013-03-19 19:06:37

标签: c# generics

我正在尝试构建一个方法,该方法将采用各种数字类型并为第二种方法预处理它们。我不确定我是应该简单地重载还是使用泛型方法。我试图使用泛型方法,但该方法似乎没有识别参数类型。代码如下。有人可以向我解释在这种情况下过载或使用通用方法是否更好?另外,如果我想使用通用方法来做到这一点,我怎么能让它工作?非常感谢你。

 public static class math
 {
      public static int nextpow2<T>(T a)
      {
           double w;
           if ( a.GetType() is sbyte   ||
                a.GetType() is byte    ||
                a.GetType() is short   ||
                a.GetType() is ushort  ||
                a.GetType() is int     ||
                a.GetType() is uint    ||
                a.GetType() is long    ||
                a.GetType() is ulong   ||
                a.GetType() is float   ||
                a.GetType() is double  ||
                a.GetType() is decimal
           ) w = (double)Convert.ChangeType(a, typeof(double));
           else
                throw new System.ArgumentException("Internal error in nextpow2: argument a is not a number!");

           return _nextpow2(w);
      }

      private static int _nextpow2(double a)
      {
           double index = Math.Abs(a);
           int p = (index > 1) ? (int)Math.Ceiling( Math.Log( index, 2.0) ) : 0;

           return p;
      }

我调用的方法如下:

 int indx = 0;
 int p = math.nextpow2(indx);

代码无法编译。我收到以下错误:

nextpow2中的内部错误:参数a不是数字!

有人可以解释一下我做错了什么吗?谢谢。

2 个答案:

答案 0 :(得分:3)

  

有人可以解释一下我做错了什么吗?

不确定。您正在检查Type对象是sbyte还是byte等。您没有检查类型是否代表类型{ {1}}等等......你问的是的值是sbyte。从来没有这样的情况。 (这就是你得到编译时错误的原因。)

可以使用:

sbyte

但我可能不会。我不会将它作为通用方法完全。如果你真的想要这个功能,我会写:

if (a.GetType() == typeof(byte) ||
    // etc)

注意这是如何做一个的事情:将参数转换为private static readonly HashSet<Type> ValidTypes = new HashSet<Type> { typeof(sbyte), typeof(byte), /* etc */ }; public static double ConvertToDouble(object x) { if (x == null) { throw new ArgumentNullException("x"); } if (!ValidTypes.Contains(x.GetType()) { throw new ArgumentException("..."); } return Convert.ChangeType(x, typeof(double)); } 。然后调用double是没有意义的 - 如果他们想要,调用者就可以这么做。

此外,你写了两个相互矛盾的事情:

  

代码无法编译。我收到以下错误:
  nextpow2中的内部错误:参数a不是数字!

如果编译失败(这是我所期望的,顺便说一句)那么你就无法运行代码,这意味着你无法获得异常。您需要区分编译时错误,如下所示:

_nextpow2

执行时间例外。

此外,您的类和方法名称都违反了正常的.NET命名约定。

答案 1 :(得分:2)

你可以说

a is sbyte

或者说

a.GetType() == typeof(sbyte)

但将它混合到a.GetType() is sbyte中是没有意义的。您应该收到编译器警告!对于a.GetType(),将是一个派生自System.Type的对象(实际上它将是System.RuntimeType),因此它永远不会派生自sbyte(因为sbytesbyte密封,作为结构,而ValueType本身仅来自Objectpublic static int Nextpow2(double a) { ... } )。

比通用方法更好的解决方案是:

decimal

double以外的所有数字类型都可以隐式转换为int indx = 0; int p = math.Nextpow2(indx); 。因此,使用上述签名,您可以按照自己的方式使用它:

{{1}}