Showing posts with label Generics. Show all posts
Showing posts with label Generics. Show all posts

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

Monday, June 16, 2008

Generics with Predicates

A predicate is pointer to a boolean function which you can use for querying generic lists.
With these methods, coding against generic lists will be much easier. But one problem with these predicates is that the only parameter in the function is of the type of the generic. A solution for this is refactoring the predicate to a class, where you can provide these parameters to properties or the constructor.

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


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

public class PredicateExamples
{
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 tomorrow = new DateRange (DateTime.Today.AddDays(1), DateTime.Today.AddDays(2))

//get a boolean if there is an event tomorrow
bool tomorrowHasEvents = events.Exists(tomorrow.InPeriod);

//get events for tomorrow
List tomorrowEvents = events.FindAll(tomorrow.InPeriod);

//get first event for tomorrow (first item in list!)
DateTime tomorrowFirstEvent = events.Find(tomorrow.InPeriod);
//get last event for tomorrow
DateTime tomorrowLastEvent = events.FindLast(tomorrow.InPeriod);

//get the index of the first event for tomorrow
int tomorrowFirstEventIndex = events.FindIndex(tomorrow.InPeriod);
//get the index of the last event for tomorrow
int tomorrowLastEventIndex = events.FindLastIndex(tomorrow.InPeriod);

//remove all events for tomorrow
int removedItems = events.RemoveAll(tomorrow.InPeriod);

//are all events in the list tomorrow
bool allEventsTomorrow = events.TrueForAll(tomorrow.InPeriod);

}
}