为什么我的通用扩展方法说无法从 T 转换为......或..到T
本文关键字:转换 我的 扩展 方法 为什么 | 更新日期: 2023-09-27 18:31:54
进一步回答我的问题
https://stackoverflow.com/questions/10241345/any-percentage-function-in-net
https://stackoverflow.com/questions/9942202/percentage-of-each-element-in-linq
我想在 .Net 4.0 中创建一个通用扩展方法,该方法将生成列表项的百分比与列表的总和。此列表将仅属于数字类型。
我的代码是
public static T Percentage<T>(this T array) where T: ? // What should come in place of ?
{
double[] darray = (double[])T; // Error convert type 'T' to 'double[]'
darray = darray.Select(x=> x * 100 / darray.Sum()).ToArray();
return darray; // Error convert type 'double[]' to 'T'
}
我想这样称呼它
double[] MD = {8.0,21.0,25.0,13.0,26.0,37.0,37.0,33.0,71.0,9.0};
MD = MD.Percentage().ToArray();
我做错了什么;
不能用"数字"值约束类型。这在某种程度上是框架的限制。
你最好的办法是这样做:
public static IEnumerable<double> Percentage(this IEnumerable<int> values)
{
var sum = values.Sum();
return values.Select(v => (double)v / (double)sum).ToArray();
}
public static IEnumerable<double> Percentage(this IEnumerable<long> values)
{
var sum = values.Sum();
return values.Select(v => (double)v / (double)sum).ToArray();
}
public static IEnumerable<double> Percentage(this IEnumerable<double> values)
{
var sum = values.Sum();
return values.Select(v => v / sum).ToArray();
}
本质上,您需要为要支持的每种类型生成重载。
不可能有你想要的类型约束。有关详细信息,请查看将泛型类型参数约束为数值类型。
由于没有太多的数值类型(整数/浮点/双精度/十进制),因此简单地提供具体的实现可能更容易。
更多选项
- 要求 IConvertible 并使用 IConvertible.ToDouble 以双精度执行所有数学运算
- 使用此处提到的 https://jonskeet.uk/csharp/miscutil/usage/genericoperators.html C#:数字的通用接口。
有一种有效的替代方法,即传入选择器函数,该函数允许您在调用 Percent 时转换为双精度。这是扩展方法:
public static double[] Percentage<T>(this T[] array, Func<T,double> selector)
{
var doubles = array.Select(selector);
var sum = doubles.Sum();
var result = doubles.Select(x => x * 100 / sum).ToArray();
return result;
}
用法:
double[] MD = {8.0,21.0,25.0,13.0,26.0,37.0,37.0,33.0,71.0,9.0};
var MDPercent = MD.Percentage(x => x).ToArray();
然后你可以有一个简单的双重版本:
public static double[] Percentage(this double[] array)
{
return Percentage(array, x => x);
}
或 int 版本:
public static double[] Percentage(this int[] array)
{
return array.Percentage(x => (double)x);
}
哪些使用起来更简单:
var MDPercent = MD.Percentage().ToArray();