调用带有T类型参数的泛型方法
本文关键字:泛型方法 类型参数 调用 | 更新日期: 2023-09-27 18:04:57
我试图建立一个方法,将采取各种数字类型和预处理他们的第二个方法。我不确定我是否应该简单地重载或使用泛型方法。我试图使用通用方法,但该方法似乎不识别参数类型。代码如下。有人能向我解释一下,在这种情况下,重载或使用泛型方法是否更好?此外,如果我想使用泛型方法来实现这一点,我该如何使它工作呢?非常感谢。
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不是数字!
谁能解释一下我做错了什么?谢谢你。
谁能解释一下我做错了什么?
确定。检查Type
对象是sbyte
还是byte
,等等。您没有检查类型是否代表 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
是没有意义的——如果调用者想这样做的话,它很容易做到。
另外,你写了两件相互矛盾的事情:
代码编译失败。我得到以下错误:
nextpow2内部错误:参数a不是数字!
如果它编译失败(这是我所期望的,顺便说一句),那么你不能运行代码,这意味着你不能得到异常。您需要区分如下的编译时错误:
warning CS0184: The given expression is never of the provided ('sbyte') type
和执行时异常。
而且,你的类名和方法名都违反了正常的。net命名约定。
你也可以说
a is sbyte
或
a.GetType() == typeof(sbyte)
但将其混合到a.GetType() is sbyte
中没有意义。你应该得到一个编译器警告!因为a.GetType()
是一个从System.Type
派生的对象(实际上是System.RuntimeType
),因此它永远不能从sbyte
派生(因为sbyte
是密封的,是一个结构体,而sbyte
本身只从ValueType
和Object
派生)。
一个比泛型方法更好的解决方案是:
public static int Nextpow2(double a)
{
...
}
除decimal
外的所有数值类型都可以隐式转换为double
。因此,有了上面的签名,你可以按照你想要的方式使用它:
int indx = 0;
int p = math.Nextpow2(indx);