Checking timeouts made more readable
- by Markus
I have several situations where I need to control timeouts in a technical application. Either in a loop or as a simple check. Of course – handling this is really easy, but none of these is looking cute.
To clarify, here is some C# (Pseudo) code:
private DateTime girlWentIntoBathroom;
girlWentIntoBathroom = DateTime.Now;
do
{
// do something
} while (girlWentIntoBathroom.AddSeconds(10) > DateTime.Now);
or
if (girlWentIntoBathroom.AddSeconds(10) > DateTime.Now)
MessageBox.Show("Wait a little longer");
else
MessageBox.Show("Knock louder");
Now I was inspired by something a saw in Ruby on StackOverflow:
Now I’m wondering if this construct can be made more readable using extension methods. My goal is something that can be read like
“If girlWentIntoBathroom is more than 10 seconds ago”
1st attempt
if (girlWentIntoBathroom > (10).Seconds().Ago())
MessageBox.Show("Wait a little longer");
else
MessageBox.Show("Knock louder");
So I wrote an extension for integer that converts the integer into a TimeSpan
public static TimeSpan Seconds(this int amount)
{
return new TimeSpan(0, 0, amount);
}
After that, I wrote an extension for TimeSpan like this:
public static DateTime Ago(this TimeSpan diff)
{
return DateTime.Now.Add(-diff);
}
This works fine so far, but has a great disadvantage. The logic is inverted! Since girlWentIntoBathroom is a timestamp in the past, the right side of the equation needs to count backwards: impossible.
Just inverting the equation is no solution, because it will invert the read sentence as well.
2nd attempt
So I tried something new:
if (girlWentIntoBathroom.IsMoreThan(10).SecondsAgo())
MessageBox.Show("Knock louder");
else
MessageBox.Show("Wait a little longer");
IsMoreThan() needs to transport the past timestamp as well as the span for the extension SecondsAgo(). It could be:
public static DateWithIntegerSpan IsMoreThan(this DateTime baseTime, int span)
{
return new DateWithIntegerSpan() { Date = baseTime, Span = span };
}
Where DateWithIntegerSpan is simply:
public class DateWithIntegerSpan
{
public DateTime Date {get; set;}
public int Span { get; set; }
}
And SecondsAgo() is
public static bool SecondsAgo(this DateWithIntegerSpan dateAndSpan)
{
return dateAndSpan.Date.Add(new TimeSpan(0, 0, dateAndSpan.Span)) < DateTime.Now;
}
Using this approach, the English sentence matches the expected behavior. But the disadvantage is, that I need a helping class (DateWithIntegerSpan).
Has anyone an idea to make checking timeouts look more cute and closer to a readable sentence? Am I a little too insane thinking about something minor like this?