Method using Func <T, TResult> as parameters
I need help simplifying my method
I have this method
public double ComputeBasicAmount(double basicLimit, double eligibleAmt) { return basicLimit * eligibleAmt; } Sample Usage:
Foo foo = new Foo(100, 1000); double basicAmt = ComputeBasicAmount(foo.BasicLimit, foo.EligibleAmt) The problem here is that I want eligibleAmt to be dynamic , because sometimes itβs really not only eligbleAmt that I pass to the method .. like this
Foo foo = new Foo(100, 1000); double basicAmt = ComputeBasicAmount(foo.BasicLimit, foo.EligibleAmt/foo.RoomRate) My solution uses the Func delegate as a parameter, but I don't know how to use it correctly
I want something functional like this
public double ComputeBasicAmount<T>(double basicLimit, Func<T, double> multiplier) { return basicLimt * multiplier; } double basicAmt = ComputeBasicAmount<Foo>(foo.BasicLimit, x => x.EligibleAmt/x.RoomRate) Can someone help me. thanks in advance...
If the factor depends on the element, then either you will need to pass this element, or you need to return Func<T, double> :
public double ComputeBasicAmount<T>(double basicLimit, Func<T, double> multiplier, T item) { return basicLimt * multiplier(item); } ... double basicAmt = ComputeBasicAmount<Foo>( foo.BasicLimit, x => x.EligibleAmt / x.RoomRate, foo) or
public Func<T, double> ComputeBasicAmount<T>(double basicLimit, Func<T, double> multiplier) { return item => basicLimt * multiplier(item); } ... var basicAmtFunc = ComputeBasicAmount<Foo>( foo.BasicLimit, x => x.EligibleAmt / x.RoomRate); var basicAmt = basicAmntFunc(foo); If none of them is what you were looking for, explain where you want to provide the actual value of T so that you can work out a factor.
The first is very similar to just Func<double> , to calculate the multiplier, of course ... which, in turn, is pretty much like calling Func<double> when calculating the arguments, to return to the original version, which just takes two doubles.
You can declare it simply as Func<double> (this way, you are not creating a method depending on the type of Foo ), and pass any method without taking any parameters and returning double as an argument:
public static double ComputeBasicAmount(double basicLimit, Func<double> multiplier) { return basicLimit * multiplier(); } Some examples of calls:
class Foo { public double One; public double Two; } Foo f = new Foo(); double result = ComputeBasicAmount(f.One, () => f.Two); You may also have some other method returning double
public static double GetDoubleValue() { return 4.2; } ... and pass this as an argument:
double result = ComputeBasicAmount(42,GetDoubleValue); You would declare your method something like this, so the factor is a delegate that takes a Foo object and returns double:
double ComputeBasicAmount( double basicLimit, Foo foo, Func<Foo, double> multiplier) Then call it like this by passing the lambda to the factor:
double basicAmt = ComputeBasicAmount( foo.BasicLimit, foo, x => x.EligibleAmt / x.RoomRate); You should use Func<double> as you only use double result
public double ComputeBasicAmount(double basicLimit, Func<double> multiplier) { return basicLimt * multiplier(); } Then name it as follows
double basicAmt = ComputeBasicAmount<Foo>(foo.BasicLimit, x => x.EligibleAmt/x.RoomRate) But then instead you can have the usual double parameter.
Thanks guys. With your help, I was able to make my existing code more readable and functional ...
class RNB { public RNB(double roomRate, double roomDays) { RoomRate = roomRate; RoomDays = roomDays; } public double RoomRate { get; set; } public double RoomDays { get; set; } public const double BasicLimit = 100; } class HMS { public double Amount { get; set; } public const double BasicLimit = 200; } public static double ComputeBasicAmount(double basicLimit, Func<double> multiplier) { return basicLimit * multiplier(); } static void Main(string[] args) { RNB rnb = new RNB(100, 2); double result = ComputeBasicAmount(RNB.BasicLimit, () => rnb.RoomDays * rnb.RoomRate); Console.WriteLine("RNB Basic Amt: " + result.ToString()); HMS hms = new HMS() { Amount = 1000 }; result = ComputeBasicAmount(HMS.BasicLimit, () => hms.Amount); Console.WriteLine("HMS Basic Amt: " + result.ToString()); Console.Read(); } But I have another problem here. I want to exclude the passage of BasicLimit, because I think it looks superfluous here. Is it possible to put BasicLimit inside the ComputeBasicAmount method
Something like that..
public static double ComputeBasicAmount<T>(Func<T, double> multiplier, T obj) { return obj.BasicLimit * multiplier(); } But I have to put this question in a different thread, because I think its a different topic ... See you guys there ... thanks ...