我想编写一个方法,它可以采用数值类型的任意数组,并返回startIndex和endIndex之间所有元素的总和。这就是我所拥有的:
private static T SumArrayRange<T>(T[] scores, int startIndex, int endIndex)
{
T score = 0;
for (int i = startIndex; i <= endIndex; i++)
{
score += scores[i];
}
return score;
}
但编译因这两个错误而失败。
有什么方法可以强迫T只是其中一种数字类型(长,双等)?或者他们是一种更优雅的解决方法?
答案 0 :(得分:11)
不,没有办法限制泛型类型参数来使用运算符,也没有好的解决方法。一个合适的接口可以是INumeric
或IArithmetic
等接口,其中包含Add
,Subtract
等方法,由int
等所有原始类型实现, long
。 MS Connect中有一个5-year old feature request for that,它仍处于活动状态。最新消息是:
不幸的是,我们不得不削减我们在.NET Framework 4.0中解决此问题的计划。
在那之前,你将被降级为:
AddObject
,SubtractObject
等方法,这些方法使用反射并实现相应的VB语义运营商) - 易于使用,但仍然很慢if (x is int) ... else if (x is double) ...
语句。答案 1 :(得分:7)
另一种方法是使用已经可用的LINQ工具,而不是自己编写。例如:
var mySum = myCollection.Skip(startIndex).Take(count).Sum();
由于所有内置数值类型都存在Sum扩展方法,因此您不必担心编写自己的数字类型。当然,如果你的代码的“myCollection”变量已经是泛型集合类型,这将不起作用。
答案 2 :(得分:4)
答案 3 :(得分:1)
您无法约束T
允许+=
运算符工作的类型。这是因为.NET没有类型意味着 numeric 。
答案 4 :(得分:1)
解决方案位于动态关键字中。
T score = default(T)
for (int i = startIndex; i <= endIndex; i++)
{
score += (dynamic)scores[i];
}
return score;
这是一个名为后期绑定的概念。
答案 5 :(得分:0)
这是因为T可以是任何类型。如果T
是HttpWebRequest
,您可以为其指定0,还是可以在其上使用+ =运算符?
您可以使用
解决第一个错误T score = default(T);
我不确定你是如何处理第二个的,因为你必须将T约束为实现+ =运算符的类型。
答案 6 :(得分:0)
Generic constraints是我能想到的唯一可能性。但是,喝醉了,我无法准确地测试它!
答案 7 :(得分:0)
我可能是傻瓜,但不会int.Parse()解决这个问题吗?
答案 8 :(得分:0)
这是我的变种
使用类型为T的二进制运算符“add”作为默认值 但是提供了为某些指定类型自定义添加功能的功能,并且仅为其余类型使用默认二进制添加 (如果没有为类型T定义二进制加法,则在运行时抛出异常)。
private static Func<T, T, T> CreateAdd<T>()
{
Func<T, T, T> addMethod = null;
Expression<Func<T, T, T>> addExpr = null;
if (typeof(T) == typeof(string))
{
//addExpr = (Expression<Func<T, T, T>>)((a, b) => ((T)(object)((string)(object)a + (string)(object)b)));
//addMethod = addExpr.Compile();
addMethod = (a, b) => {
string aa = (string)(object)a;
string bb = (string)(object)b;
double da;
double db;
double.TryParse(aa, out da);
double.TryParse(bb, out db);
double c = da + db;
string res = c.ToString();
return (T)(object)res;
}; // End Delegate addMethod
}
else
{
ParameterExpression lhs = Expression.Parameter(typeof(T), "lhs");
ParameterExpression rhs = Expression.Parameter(typeof(T), "rhs");
addExpr = Expression<Func<T, T, T>>.Lambda<Func<T, T, T>>(
Expression.Add(lhs, rhs),
new ParameterExpression[] { lhs, rhs }
);
addMethod = addExpr.Compile();
}
return addMethod;
}
// MvcTools.Aggregate.Functions.Sum<T>(vals);
public static T Sum<T>(params T[] vals)
{
T total = default(T);
//Enumerable.Aggregate(vals, delegate(T left, T right) { return left + right; });
Func<T, T, T> addMethod = CreateAdd<T>();
foreach (T val in vals)
{
total = addMethod(total, val);
}
return total;
} // End Function Sum
示例:
int[] vals = new int[] { 1, 2, 3, 4, 5 };
int sum = MvcTools.Aggregate.Functions.Sum<int>(vals);
double[] dvals = new double[] { 1, 2, 3, 4, 5 };
double dsum = MvcTools.Aggregate.Functions.Sum<double>(dvals);
string[] strs = new string[] { "1", "2", "3", "4", "5" };
string str = MvcTools.Aggregate.Functions.Sum<string>(strs);
输出:15,15.0,“15”