我正在尝试构建一个方法,该方法将采用各种数字类型并为第二种方法预处理它们。我不确定我是应该简单地重载还是使用泛型方法。我试图使用泛型方法,但该方法似乎没有识别参数类型。代码如下。有人可以向我解释在这种情况下过载或使用通用方法是否更好?另外,如果我想使用通用方法来做到这一点,我怎么能让它工作?非常感谢你。
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不是数字!
有人可以解释一下我做错了什么吗?谢谢。
答案 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
(因为sbyte
是sbyte
密封,作为结构,而ValueType
本身仅来自Object
和public static int Nextpow2(double a)
{
...
}
)。
比通用方法更好的解决方案是:
decimal
除double
以外的所有数字类型都可以隐式转换为int indx = 0;
int p = math.Nextpow2(indx);
。因此,使用上述签名,您可以按照自己的方式使用它:
{{1}}