在C#中定义泛型可以达到代码的重复利用,但是如何将泛型方法限制为数值类型(如int,double,float 等)并对其进行进行四则运算呢?
其实:C#不支持这一点。Hejlsberg描述了不实现此特性的原因。在接受布鲁斯·埃克尔的采访时:
现在还不清楚增加的复杂性是否值得你得到的小收益。如果在约束系统中不直接支持要做的事情,可以使用工厂模式来完成。你可以Matrix<T>
例如,在这方面Matrix
您想要定义一个点乘积方法。当然,这意味着你最终需要了解如何将2相乘。T
S,但你不能说这是一种约束,至少如果T
是int
, double
,或float
..但你能做的就是Matrix
把论点当作论据Calculator<T>
,以及Calculator<T>
,有一个名为multiply
..你去实现它,然后把它传递给Matrix
.
那么如果我们需要一个求数组和的泛型方法怎么办?
我们不妨使用下列方法实现
public static T Sum<T>(params T[] values) where T:struct
{
//逻辑实现部分
}
首先我们应该知道struct的范围要远大于数值类型;即(int,float,double 等)是struct的一部分,退而求其次,我们将输入的值限制为struct,那么可以很大程度上将输入值限制;
那么struct值类型提供了如下Equals、GetType、GetHashCode、ToString四个方法,系统并无提供四则运算的方法,我们如何对其数组进行求和呢?
接下来我们不妨如下操作:
public static T Sum<T>(params T[] values) where T:struct
{
if (values == null) return default(T);
dynamic sum = default(T);
var type = Type.GetTypeCode(values[0].GetType());
switch (type)
{
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Decimal:
{
dynamic vas = values;
for (int i = 0; i < vas.Length; i++)
{
sum += vas[i];
}
}
break;
default:
break;
}
return sum;
}
借用dynamic的特性我们可以将输入值转换成dynamic然后在进行四则运算;
特别提醒:此方法虽然可以实现数值类型的求和但是对于一些无四则运算的struct会产生异常操作,我们可以在进行数值运算前进行类型判断,若类型无四则运算操作则特别处理,
在一些取舍下,上述方法也是一个不错的方法;