Как сделать так, чтобы одна стратегия в шаблоне стратегии возвращала более одного значения

У меня реализован шаблон стратегии. Предполагается, что одна из стратегий возвращает 2 значения, а остальные — 1 значение. В настоящее время я использую out param в методе интерфейса, чтобы он был доступен для одной стратегии, которая устанавливает это значение и делает его нулевым для всех других стратегий, как в приведенном ниже примере.

Я хотел бы знать, есть ли лучший способ, чтобы эта одна стратегия возвращала несколько значений, не заставляя все другие стратегии иметь дело с этим параметром out (даже если все они собираются установить его равным нулю). Например:

public interface IContributionStrategy
{
    decimal (decimal configuredAmt, out decimal? recurrent);
}
public class Strategy1 : IContributionStrategy
{
  public Strategy1 (int param1)
  {
    this.Param = param1;
  }
  public decimal Calculate(decimal amt, out decimal? recurrent)
  {
     recurrent = somevalue;
     //some logic that uses amt and this.Param and performs calc
     return calculatedLogic;
  }
public class Strategy2 : IContributionStrategy
{
  public decimal Calculate(decimal amt, out decimal? recurrent)
  {
     recurrent = null; //having to set this to null only because its in the Calculate() in the interface and this strategy is not using the recurrent value.
     //some logic that uses amt and performs calc
     return calculatedLogic;
  }
}

person theandroid    schedule 04.07.2018    source источник
comment
IEnumerable<decimal?> возможно в качестве возвращаемого типа?   -  person mjwills    schedule 04.07.2018
comment
Или класс, в котором есть два свойства (для двух значений)?   -  person mjwills    schedule 04.07.2018
comment
Если у вас есть много стратегий, которые возвращают одно значение, и одна, которая должна возвращать несколько значений, это не похоже на то, что последние принадлежат одному и тому же месту. Как они используются?   -  person Riaan Nel    schedule 04.07.2018


Ответы (3)


Я бы предложил класс, который содержит оба.

public class CalculateResult {
    decimal amount {get;set}
    decimal? recurrent {get;set}
}
person Shane Ray    schedule 04.07.2018

Я бы посоветовал вам рассмотреть две сильные альтернативные подписи:

(1)

IEnumerable<decimal> Calculate(decimal configuredAmt);

(2)

decimal Calculate(decimal configuredAmt, Action<decimal> extra);

Вы бы реализовали их следующим образом:

(1)

public IEnumerable<decimal> Calculate(decimal amt)
{
    yield return 1m;
    yield return 42m;
    yield return 2m;
}

(2)

public decimal Calculate(decimal amt, Action<decimal> extra)
{
    extra(1m);
    extra(42m);
    return 2m;
}

Этот второй вариант может использоваться следующим образом:

var s = new Strategy1();
var extras = new List<decimal>();
decimal r = s.Calculate(1m, x => extras.Add(x));

В результате r == 2m и extras содержат 1m и 42m.

person Enigmativity    schedule 04.07.2018

Вместо того, чтобы возвращать примитивный тип данных, я бы предложил вам вернуть определенный пользователем тип данных (например, класс, структуру), содержащий всю необходимую информацию в виде свойств.

class result
{
   decimal result1;
   decimal? result2;
   .......
}
person zacs    schedule 04.07.2018