I've two method:
static int SumInt(List<string> list)
{
return list.Select(o => int.Parse(o)).Sum();
}
static float SumFloat(List<string> list)
{
return list.Select(o => float.Parse(o)).Sum();
}
How can i get a generic method such as static T Sum<T>(List<string> list) where T:struct{}
,or a method with a ValueType return: static ValueType Sum(List<string> list){}
The key point is not how to convert, but how to sum a struct or ValueType.
I would use a Dictionary<Type, Delegate>
to hold the delegate that can do the computation. You then just have to register the correct delegates at run-time and it works quite easily.
private static Dictionary<Type, Delegate> _registry = new Dictionary<Type, Delegate>();
public static void Register<S, T>(Func<string, S> parse, Func<IEnumerable<S>, T> aggregate)
{
_registry[typeof(T)] = (Func<IEnumerable<string>, T>)(xs => aggregate(xs.Select(parse)));
}
public static T Sum<T>(List<string> list) =>
((Func<IEnumerable<string>, T>)_registry[typeof(T)])(list);
Now I can write this code:
Register(int.Parse, Enumerable.Sum);
Register(float.Parse, Enumerable.Sum);
var sourceIntegers = new List<string>() { "1", "2", "3" };
var sourceFloats = new List<string>() { "1.1", "2.2", "3.3" };
Console.WriteLine(Sum<int>(sourceIntegers));
Console.WriteLine(Sum<float>(sourceFloats));
The output I get is this:
6
6.6
What makes this approach interesting is that I can do this:
Register(
x => new XElement("value", x),
xs => new XDocument(new XElement("list", xs)));
Console.WriteLine(Sum<XDocument>(sourceIntegers));
That outputs:
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>