Supponiamo di avere un calcolo matematico complicato da eseguire, che comporta l'esecuzione di rounding . Supponiamo che a volte vuoi che l'arrotondamento sia round to even (ovvero l'arrotondamento dei banchieri), ma altre volte vuoi arrotondare da zero (ovvero arrotondare [in assoluto valore] ').
Ora potresti scrivere due metodi:
double DoTheCalculationWithRoundToEven(double input1, double input2)
{
var intermediate1 = Math.Pow(input1, input2);
// more calculations...
var intermediate5 = Math.Round(intermediate4, MidpointRounding.ToEven);
// more calculations...
var intermediate10 = Math.Abs(intermediate9);
return intermediate10;
}
double DoTheCalculationWithRoundAwayFromZero(double input1, double input2)
{
var intermediate1 = Math.Pow(input1, input2);
// more calculations...
var intermediate5 = Math.Round(intermediate4, MidpointRounding.AwayFromZero);
// more calculations...
var intermediate10 = Math.Abs(intermediate9);
return intermediate10;
}
con i due metodi è lo stesso tranne per quella riga nel mezzo.
Ora funziona, MA hai codice duplicato e la possibilità molto reale che qualche futuro manutentore (ad esempio, un futuro tu) cambierà una versione di intermediate2
in intermediate3
e dimentichi l'altro .
Un tipo di delegato e un parametro possono risolvere questa duplicazione.
Prima dichiara il tipo di delegato:
public delegate double Rounder(double value);
Questo indica che un Rounder
è un metodo che accetta un double
e restituisce un double
.
Successivamente, hai un metodo di calcolo che accetta Rounder
e lo usa per arrotondare:
double DoTheCalculation(double input1, double input2, Rounder rounder)
{
var intermediate1 = Math.Pow(input1, input2);
// more calculations...
var intermediate5 = rounder(intermediate4);
// more calculations...
var intermediate10 = Math.Abs(intermediate9);
return intermediate10;
}
Infine, quando vuoi eseguire il calcolo, passa un Rounder
appropriato. Puoi scrivere tutto con i metodi:
double RounderAwayFromZero(double value)
{
return Math.Round(value, MidpointRounding.AwayFromZero);
}
// same for ToEven
quindi chiama uno di:
var result = DoTheCalculation(input1, input2, RounderAwayFromZero);
o
var result = DoTheCalculation(input1, input2, RounderToEven);
ma C # ti permette di fare tutto ciò in linea con lambdas:
var result = DoTheCalculation(input1, input2,
value => Math.Round(value, MidpointRounding.AwayFromZero));
dove l'espressione lambda definisce un metodo con la firma corretta come Rounder
.