Think this is a generic vs type specific problem.
I would like to add a unit to a string casted argument that can be an int or a float.
I tried the following, but there is problem at the time of the cast because the type is not known at compile time.
namespace ConsoleApp17
{
class Program
{
static int myInt = 1;
static float myFloat = 2f;
static void Main(string[] args)
{
string myFloatStr = "1.3";
string myIntStr = "2";
Add<float>(myFloatStr, SetNewFloatValue);
Add<int>(myIntStr, SetNewIntValue);
Console.ReadLine();
}
public static void Add<T>(string str, Action<T> action)
{
T valueToSet = (T)Math.Round(double.Parse(str) 1, 0 , MidpointRounding.AwayFromZero); //problem here, cannot convert double to T
action(valueToSet);
}
private static void SetNewFloatValue(float floatArg) {
myFloat = floatArg;
}
private static void SetNewIntValue(int intArg)
{
myInt = intArg;
}
}
}
fiddle in case its helpful.
Is method overload for each of the arguments the only solution for this, or is there a more elegant solution so that the same funtionality can be dealt with in the one same method for both types float and int?
Meaning that:
Add<float>(myFloatStr, SetNewFloatValue);
Add<int>(myIntStr, SetNewIntValue);
could be done with the one same method.
CodePudding user response:
"Generic Math" is what you want. This feature is a preview feature in .NET 6.0/C#10. It is described in detail here.
This allows method declarations such as this one:
public static TResult Sum<T, TResult>(IEnumerable<T> values)
where T : INumber<T>
where TResult : INumber<TResult>
{
TResult result = TResult.Zero;
foreach (var value in values)
{
result = TResult.Create(value);
}
return result;
}
The INumber interface is the magic of this concept. It is implemented on most numeric types now.
Previously, you had to implement that manually (by specifying your own INumber interface, with Add(), Subtract() etc. methods) or use the dynamic type to evaluate the correct types at runtime. The former was a lot of boilerplate to write for this, the later is slow.
CodePudding user response:
If you are using older versions than .Net 6, you can use Convert.ChangeType for your case.
T valueToSet = (T)Convert.ChangeType(Math.Round(double.Parse(str) 1, 0, MidpointRounding.AwayFromZero), typeof(T));
