C# 使用T类型参数调用泛型方法
我正在尝试构建一个方法,该方法将接受各种数值类型,并对它们进行预处理,以获得第二个方法。我不确定是应该简单地重载还是使用泛型方法。我尝试使用泛型方法,但该方法似乎无法识别参数类型。代码如下。有人能给我解释一下,在这种情况下,重载还是使用泛型方法更好?另外,如果我想用一个通用的方法来做这件事,我如何才能让它工作呢?多谢各位C# 使用T类型参数调用泛型方法,c#,generics,C#,Generics,我正在尝试构建一个方法,该方法将接受各种数值类型,并对它们进行预处理,以获得第二个方法。我不确定是应该简单地重载还是使用泛型方法。我尝试使用泛型方法,但该方法似乎无法识别参数类型。代码如下。有人能给我解释一下,在这种情况下,重载还是使用泛型方法更好?另外,如果我想用一个通用的方法来做这件事,我如何才能让它工作呢?多谢各位 public static class math { public static int nextpow2<T>(T a) {
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;
}
代码无法编译。我得到以下错误:
nextpow2中出现内部错误:参数a不是数字
有人能解释一下我做错了什么吗?多谢各位
有人能解释一下我做错了什么吗
当然。您正在检查类型
对象是sbyte
,还是字节
,等等。您没有检查类型是否表示sbyte
等的类型。。。您正在询问该值是否为sbyte
。从来都不是这样。(这就是为什么会出现编译时错误。)
您可以使用:
但我可能不会。我根本不会让它成为一个通用的方法。如果你真的想要功能,我会写:
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));
}
和执行时间异常
此外,类和方法名称都违反了正常的.NET命名约定
有人能解释一下我做错了什么吗
当然。您正在检查类型
对象是sbyte
,还是字节
,等等。您没有检查类型是否表示sbyte
等的类型。。。您正在询问该值是否为sbyte
。从来都不是这样。(这就是为什么会出现编译时错误。)
您可以使用:
但我可能不会。我根本不会让它成为一个通用的方法。如果你真的想要功能,我会写:
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));
}
和执行时间异常
此外,您的类和方法名称都违反了正常的.NET命名约定。您可以说
a is sbyte
或者说
a.GetType() == typeof(sbyte)
但是把它混入a中是没有意义的。GetType()是sbyte
。你应该得到一个编译器警告!对于a.GetType()
将是从System.Type
派生的对象(实际上它将是System.RuntimeType
),因此它永远不能从sbyte
派生(因为sbyte
是密封的,是一个结构,sbyte
本身只从ValueType
和Object
派生)
比一般方法更好的解决方案是:
public static int Nextpow2(double a)
{
...
}
除了decimal
之外的所有numeric类型都可以隐式转换为double
。因此,使用上述签名,您可以按照自己的方式使用它:
int indx = 0;
int p = math.Nextpow2(indx);
你可以说
a is sbyte
或者说
a.GetType() == typeof(sbyte)
但是把它混入a是没有意义的。GetType()是sbyte
。你应该得到一个编译器警告!因为a.GetType()
将是一个从System.Type
派生的对象(实际上它将是System.RuntimeType
),因此它永远不能从sbyte
派生(因为sbyte
是密封的,是一个结构,sbyte
本身只从ValueType
和Object
派生)
比一般方法更好的解决方案是:
public static int Nextpow2(double a)
{
...
}
除了decimal
之外的所有numeric类型都可以隐式转换为double
。因此,使用上述签名,您可以按照自己的方式使用它:
int indx = 0;
int p = math.Nextpow2(indx);
为什么不直接使用非通用签名
nextpow2(双a)
?您想要支持的许多类型已经隐式转换为双精度
。如果有人将我的十进制数也更改为双精度,我会非常不高兴。我正在尝试创建一个通用方法。可能有人会传入一个没有隐式转换为双精度的参数,我想抓住这种情况。非常简单关于将十进制转换为双精度的观点很好。谢谢。即使您同时编写了方法及其调用代码,最好的做法是假设调用方使用该方法时不知道其内部实现。在这种情况下,该方法很难使用,因为它对其输入施加了未知规则。如果您希望该方法运行在double
上设置参数类型double
,让调用者担心输入是否合适。为什么不使用非通用签名nextpow2(双a)
?您想要支持的许多类型已经隐式转换为双精度
。如果有人将我的十进制数也更改为双精度,我会非常不高兴。我正在尝试创建一个通用方法。可能有人会传入一个没有隐式转换为双精度的参数,我想抓住这种情况。非常简单关于将十进制转换为双精度的观点很好。谢谢。即使您同时编写了方法及其调用代码,最好的做法是假设调用方使用该方法时不知道其内部实现。在这种情况下,该方法很难使用,因为它对其输入施加了未知规则。如果您希望该方法运行在double
上,将参数类型设置为double
,让调用者担心输入是否合适。Duh。这是完全有道理的。我不知道我怎么会错过这一个。我可以问一下为什么你不会这样做吗?如果你想走“通用数学”的路线,也推荐使用:Skeet的“杂项实用程序库”(还有马克,对吗,乔恩?):@PBrenek:你真的没有编写一个正常意义上的泛型方法。它并不是真的可以处理任何类型,也不是说你要将该值作为该类型的值来处理-你所做的只是调用Convert.ChangeType
。你认为使它泛型有什么好处?@Jonsket:你缺少了一个返回类型!O_O;p@Jons