Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method using Func<T,TResult> as parameters

I need some help on 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 I want the eligibleAmt to be dynamic because sometimes it's not really only the eligbleAmt what I'm passing to the method.. like this

Foo foo = new Foo(100, 1000);
double basicAmt = ComputeBasicAmount(foo.BasicLimit, foo.EligibleAmt/foo.RoomRate)

My solution is use the Func delegate as a parameter but i don't know how to use it properly

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...

like image 554
CSharpNoob Avatar asked Dec 22 '22 23:12

CSharpNoob


2 Answers

If the multiplier depends on the item then either you'll need to pass the item as well, or you'll need to return a 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 neither of those is what you were looking for, please explain where you want the actual value of T to be provided so that you can work out the multiplier.

The first is very similar to just having a Func<double> to compute the multiplier, of course... which in turn is pretty much like calling that Func<double> when computing the arguments, to get back to your original version which just takes two doubles.

like image 73
Jon Skeet Avatar answered Dec 25 '22 22:12

Jon Skeet


You can declare it simply as a Func<double> (that way you are not making the method dependent on the Foo type), and pass any method taking no parameters and returning a double as argument:

public static double ComputeBasicAmount(double basicLimit, Func<double> multiplier)
{
    return basicLimit * multiplier();
}

Some example calls:

class Foo
{
    public double One;
    public double Two;
}


Foo f = new Foo();
double result = ComputeBasicAmount(f.One, () => f.Two);

You can also have some other method returning a double

public static double GetDoubleValue()
{
    return 4.2;
}

...and pass that as argument:

double result = ComputeBasicAmount(42,GetDoubleValue);
like image 30
Fredrik Mörk Avatar answered Dec 25 '22 23:12

Fredrik Mörk