Метод с использованием Func <T, TResult> в качестве параметров - PullRequest
4 голосов
/ 10 сентября 2010

Мне нужна помощь в упрощении моего метода

У меня есть этот метод

public double ComputeBasicAmount(double basicLimit, double eligibleAmt)
{
  return basicLimit * eligibleAmt;
}

пример использования:

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

Проблема здесь в том, что я хочу получить право на участиебыть динамическим , потому что иногда это не только eligbleAmt, что я передаю методу .. вот так

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

Мое решение - использовать Func делегировать в качестве параметра, но я не знаю, как правильно его использовать

я хочу что-то функциональное, подобное этому

public double ComputeBasicAmount<T>(double basicLimit, Func<T, double> multiplier)
{

 return basicLimt * multiplier;
}

double basicAmt = ComputeBasicAmount<Foo>(foo.BasicLimit, x => x.EligibleAmt/x.RoomRate)

может кто-нибудь мне помочь.заранее спасибо ...

Ответы [ 5 ]

5 голосов
/ 10 сентября 2010

Если множитель зависит от элемента, то либо вам также нужно будет передать элемент, или вам необходимо вернуть 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)

или

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);

Если ни один из них не является тем, что вы искали, пожалуйста, объясните, где вы хотите указать фактическое значение T, чтобы вы могли определить множитель.

Первое очень похоже на просто Func<double> для вычисления множителя, конечно ... что, в свою очередь, очень похоже на , вызывающий , который Func<double> при вычислении аргументов, чтобы получить вернуться к исходной версии, которая занимает всего два раза.

4 голосов
/ 10 сентября 2010

Вы можете объявить его просто как Func<double> (таким образом, вы не делаете метод зависимым от типа Foo), и передать любой метод, не имеющий параметров, и возвращающий в качестве аргумента double:

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

Некоторые примеры звонков:

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


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

Вы также можете использовать другой метод, возвращающий double

public static double GetDoubleValue()
{
    return 4.2;
}

... и передать это в качестве аргумента:

double result = ComputeBasicAmount(42,GetDoubleValue);
0 голосов
/ 10 сентября 2010

Спасибо, ребята, с вашей помощью я смог сделать свой существующий код намного более читабельным и функциональным ...

    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();
    }

Но у меня есть еще одна проблема .. Я хочу устранить прохождениеBasicLimit, потому что я думаю, что это выглядит избыточным здесь.Можно ли поместить BasicLimit в метод ComputeBasicAmount

Что-то вроде этого ..

 public static double ComputeBasicAmount<T>(Func<T, double> multiplier, T obj)
  {

      return obj.BasicLimit * multiplier();
  }

Но я должен поставить этот вопрос в другой теме, потому что я думаю, что это другая тема ...Увидимся, ребята, там ... спасибо ...

0 голосов
/ 10 сентября 2010

Вы должны использовать Func<double>, так как вы используете только двойной результат

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

Тогда назови это так

double basicAmt = ComputeBasicAmount<Foo>(foo.BasicLimit, x => x.EligibleAmt/x.RoomRate)

Но тогда вы могли бы использовать обычный двойной параметр.

0 голосов
/ 10 сентября 2010

Вы бы объявили свой метод примерно так, поэтому множитель - это делегат, который принимает объект Foo и возвращает значение типа double:

double ComputeBasicAmount(
   double basicLimit, Foo foo, Func<Foo, double> multiplier)

Затем назовите это так, передав лямбду в множитель:

double basicAmt = ComputeBasicAmount(
   foo.BasicLimit, foo, x => x.EligibleAmt / x.RoomRate);
...