I'm writing a financial app that has to get data over a set of dates.
The user specifies the start date, end date, and frequency from a list of choices. (daily, weekly, monthly, quarterly, semi, annually).
There's also a preference option that allows the user to choose whether each period should be the same length ("monthly" = every 30 days vs. same day number of every month)
To avoid redoing the comparison in the loop, and to avoid duplicating code, 'use delegates' popped into my head. Suggestions please? Be brutal, it's the best way for me to learn.
public partial class FinancialApp
{
delegate void moveDateDelegate(ref DateTime d);
class MyDelegateClass
{
public int dateinterval;
public void quickAdd(ref DateTime d)
{
d = d.AddDays(dateinterval);
}
public static void daily(ref DateTime d)
{
d = d.AddDays(1);
}
public static void weekly(ref DateTime d)
{
d = d.AddDays(7);
}
public static void monthly(ref DateTime d)
{
d = d.AddMonths(1);
}
public static void quarterly(ref DateTime d)
{
d = d.AddMonths(3);
}
public static void semily(ref DateTime d)
{
d = d.AddMonths(6);
}
public static void annually(ref DateTime d)
{
d = d.AddYears(1);
}
}
static List<KeyValuePair<double, string[]>> getAllCurveTickers(string security,
double startdate,
double enddate,
char freq,
bool? fill,
bool quick)
{
var retval = new List<KeyValuePair<double, string[]>>();
DateTime d = DateTime.FromOADate(startdate);
moveDateDelegate moveDate;
MyDelegateClass mydc=new MyDelegateClass();
if (quick)
{
d = DateTime.Today;
moveDate = new moveDateDelegate(mydc.quickAdd);
switch (freq)
{
case 'D':
mydc.dateinterval = 1;
break;
case 'W':
mydc.dateinterval = 7;
break;
case 'M':
mydc.dateinterval = 30;
break;
case 'Q':
mydc.dateinterval = 90;
break;
case 'S':
mydc.dateinterval = 182;
break;
case 'A':
mydc.dateinterval = 365;
break;
default:
mydc.dateinterval = 1;
break;
}
} else
{
d = DateTime.FromOADate(startdate);
switch (freq)
{
case 'D':
moveDate = new moveDateDelegate(MyDelegateClass.daily);
break;
case 'W':
moveDate = new moveDateDelegate(MyDelegateClass.weekly);
break;
case 'M':
moveDate = new moveDateDelegate(MyDelegateClass.monthly);
break;
case 'Q':
moveDate = new moveDateDelegate(MyDelegateClass.quarterly);
break;
case 'S':
moveDate = new moveDateDelegate(MyDelegateClass.semily);
break;
case 'A':
moveDate = new moveDateDelegate(MyDelegateClass.annually);
break;
default:
moveDate = new moveDateDelegate(MyDelegateClass.daily);
break;
}
}
do
{
retval.Add(new KeyValuePair<double, string[]>(d.ToOADate(),
make_icurve_tickers(security, d.ToOADate(), fill)));
moveDate.Invoke(ref d);
} while (startdate <= enddate);
return retval;
}
I know there's still a lot of duplicated code, but I don't see how to get around this. Anonymous methods? That seems messier.
I browsed a few other questions, which sort of steer toward dictionaries of actions, which I'm not able to grok, and I don't see how it improves.