C# 将常规参数转换为整数或从整数转换为常规参数
我想编写一个泛型类,该类用于处理内置类型,如C# 将常规参数转换为整数或从整数转换为常规参数,c#,generics,casting,C#,Generics,Casting,我想编写一个泛型类,该类用于处理内置类型,如byte和ushort。在内部计算中,我需要将泛型类型转换为整数,然后再转换回泛型类型。我找到了编译此类代码的方法,例如: class Test<T> where T : struct, IConvertible { public static T TestFunction(T x) { int n = Convert.ToInt32(x); T result = (T)Convert.Cha
byte
和ushort
。在内部计算中,我需要将泛型类型转换为整数,然后再转换回泛型类型。我找到了编译此类代码的方法,例如:
class Test<T> where T : struct, IConvertible
{
public static T TestFunction(T x)
{
int n = Convert.ToInt32(x);
T result = (T)Convert.ChangeType(n, typeof(T));
return result;
}
}
类测试,其中T:struct,IConvertible
{
公共静态测试函数(TX)
{
int n=转换为32(x);
T结果=(T)Convert.ChangeType(n,typeof(T));
返回结果;
}
}
我认为,如果在计算循环中使用这种转换,可能会显著降低性能。有没有更好的方法进行这些转换?经过思考,我很高兴由于这个问题和一些答案,我解决了我的一个老问题:在泛型T上使用操作: 首先是Cast示例(根据OP的要求) 在一般情况下,乘法速度比直接乘法慢3倍(在释放模式下,无调试) 显然,从乘法开始做其他运算很简单
(有趣的是,我非常熟悉
表达式
树,但我从未想过使用静态类作为包含各种类型的“字典”。我总是做类似字典
的事情,而不是让.NET通过泛型类专门化来“处理”字典。)int
到T
的转换有点棘手。我想你可以在这里使用Expression
class
Test
类应该是这样的:
class Test<T> where T : struct, IConvertible
{
private static Func<int, T> _getInt;
static Test()
{
var param = Expression.Parameter(typeof(int), "x");
UnaryExpression body = Expression.Convert(param, typeof(T));
_getInt = Expression.Lambda<Func<int, T>>(body, param).Compile();
}
public static T TestFunction(T x)
{
int n = Convert.ToInt32(x);
T result = _getInt(n);
return result;
}
}
类测试,其中T:struct,IConvertible
{
私有静态函数;
静态测试()
{
var param=表达式参数(typeof(int),“x”);
UnaryExpression body=Expression.Convert(param,typeof(T));
_getInt=Expression.Lambda(body,param.Compile();
}
公共静态测试函数(TX)
{
int n=转换为32(x);
T结果=_getInt(n);
返回结果;
}
}
它在静态构造函数中为您准备
\u getInt=x=>(T)x
,并在以后使用它,将int
转换为T
这方面的性能基准是什么,否则需要改进哪些人?更不用说你怎么知道这是一个真正的问题了。@GrantThomas-包括Convert.ToInt32
和Convert.ChangeType
acceptObject
参数。这意味着,此代码需要装箱。我可以用另一种方式问这个问题:有可能避免装箱吗?你可以,甚至可以使装箱更快,但这仍然不是问题。不管怎样,net对32位整数进行了优化。看得很有趣。动态击败拳击?我现在正在测试这个,谢谢。@AlexFarber我没有做过任何纯拳击方法。不能完全取消绑定到其他类型。如果T是长的
,并且tx
,(int)(object)x
是无效的异常。试试intres=(int)(object)5L
真的很有趣。令人惊讶的是,使用dynamic
可以获得与使用Convert函数相同的性能。使用表达法会有更好的表现,谢谢。我希望接受你的答案,特别是在奇怪的否决票之后,但你用你自己问题的答案取代了它:)我放弃投票,接受另一个答案。希望本次讨论能对SO用户有所帮助。谢谢,使用预编译lambda可以提高函数性能。我还将预编译lambda在另一个方向(T到int)匹配,并在直方图计算方面获得了显著的性能提升。这将减少50%以上的执行时间!直方图函数在装箱上浪费了大部分时间,这是Convert.ToInt32和Convert.ChangeType函数的一部分。这真的很有趣!稍后我会亲自做一些测试!在您的测试套件中,T
是什么类型?因为Convert.ToInt32
有一个重载,它以byte
作为参数,所以这里应该没有装箱。好的,我知道这里发生了什么。实际上,Convert.ToInt32(byte)
比byte.ToInt32
好得多!
public static class Multiply<T>
{
public static readonly Func<T, T, T> Do;
static Multiply()
{
var par1 = Expression.Parameter(typeof(T));
var par2 = Expression.Parameter(typeof(T));
Do = Expression.Lambda<Func<T, T, T>>(Expression.Multiply(par1, par2), par1, par2).Compile();
}
}
int x = Conv<T, int>.Do(someTValue);
T res = Multiply<T, T>.Do(someTValue1, someTValue2);
class Test<T> where T : struct, IConvertible
{
private static Func<int, T> _getInt;
static Test()
{
var param = Expression.Parameter(typeof(int), "x");
UnaryExpression body = Expression.Convert(param, typeof(T));
_getInt = Expression.Lambda<Func<int, T>>(body, param).Compile();
}
public static T TestFunction(T x)
{
int n = Convert.ToInt32(x);
T result = _getInt(n);
return result;
}
}