Tuesday, June 17, 2008

Generics with Actions

An action is pointer to a function with no return value which you can use for working with generic lists. It looks like the Predicate functions, but the referenced method won't return a boolean value.

Still, the only parameter in the function is of the type of the generic. In this example, I extend the DateRange class with an Action.

An example of such an implementation:

/// <summary>
/// DateRange is a helper class to work with dates
/// </summary>
public class DateRange
{
private DateTime _startDate = DateTime.MinValue;
private DateTime _endDate = DateTime.MaxValue;

public DateTime StartDate
{
get { return _startDate; }
}
public DateTime EndDate
{
get { return _endDate; }
}

public DateRange(DateTime startDate, DateTime endDate)
{
_startDate = startDate;
_endDate = endDate;
}

/// <summary>
/// Gets the IsInPeriod method.
/// </summary>
/// <value>The in period.</value>
public Predicate<DateTime> InPeriod
{
get { return IsInPeriod; }
}

/// <summary>
/// Determines whether the specified date is in the period set by startdate and enddate.
/// </summary>
/// <param name="date">The date.</param>
/// <returns>
/// <c>true</c> if the specified date is in the period; otherwise, <c>false</c>.
/// </returns>
private bool IsInPeriod(DateTime date)
{
if ((date >= StartDate) && (date < EndDate))
{
return true;
}
else
{
return false;
}
}

/// <summary>
/// Gets the WriteNumberOfDaysFromStartDate method.
/// </summary>
/// <value>The write number of days till end.</value>
public Action<DateTime> WriteNumberOfDaysFromStart
{
get { return WriteNumberOfDaysFromStartDate; }
}
/// <summary>
/// Writes the number of days from the start date of the period.
/// </summary>
/// <param name="date">The date.</param>
private void WriteNumberOfDaysFromStartDate(DateTime date)
{
Console.WriteLine("{0} days to go", ((TimeSpan)(date - StartDate)).Days);
}
}


You can now use this conditional predicate with different Generic methods.

public class ActionExamples
{
public static void Main()
{
// fill an example list
List events = new List();
events.Add(DateTime.Now.AddDays(-1));
events.Add(DateTime.Now.AddDays(-2));
events.Add(DateTime.Now);
events.Add(DateTime.Now.AddDays(1));
events.Add(DateTime.Now.AddDays(2));
events.Add(DateTime.Now.AddDays(3));
events.Add(DateTime.Now.AddDays(4));

//create a DateRange object for tomorrow
DateRange nextMonth = new DateRange (new DateTime(2008,7,1), new DateTime(2008,7,31) )

//get events for next month
List nextMonthEvents = events.FindAll(nextMonth.InPeriod);

//write days from start of nextMonth to console
events.ForEach(nextMonth.WriteNumberOfDaysFromStart);
}
}

No comments: