10 More C# Extension Methods For The Holiday Season
Ahhh, it's that time of year again when we stuff the C# stocking with some Extension Methods!
Notice: This post was written for the Second Annual C# Advent Calendar (#csadvent). <commercial-voice> For the entire month of December, you can receive more than 60 articles geared towards C# for the very low price of $0.00!</commercial-voice> Thanks a lot to Matt Groves (@mgroves) for putting this together again! Awesome job, Matt!
Have I mentioned how much I love extension methods? Ok, maybe once or twice, but they are soooo useful.
I know I wrote about them last year for the First Annual C# Advent Calendar, so I thought why not do it again since everyone loves small, little morsels of C# code to make their lives better.
Here are some more of my favorite Extension Methods for C#.
IEnumerable<T>.ForEach
Ever need a simple one-liner that sets something in your list?
Simple extension, I know, but it does the trick.
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> collection, Action<T> action) { foreach (T item in collection) { action(item); } return collection; }
Usage:
customers.ForEach<Customer>(t=> t.Enabled = true);
String.IsValidIp()
As you write networking utilities, you most likely need an IP validator of some kind.
public static Boolean IsValidIp(this string ip) { if (!Regex.IsMatch(ip, "[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}")) return false;
var ips = ip.Split('.'); if (ips.Length == 4 || ips.Length == 6) { return Int32.Parse(ips[0]) < 256 && System.Int32.Parse(ips[1]) < 256 & Int32.Parse(ips[2]) < 256 & System.Int32.Parse(ips[3]) < 256; }
return false; }
Usage:
"255.255.15.22".IsValidIp() // returns true;
DateTime.ToFormattedDateTime(bool includeTime)
I've been using this on my blog for as long as I can remember.
This formats the DateTime of a blog post to make it a little prettier under the post's primary image.
public static string ToFormattedDateTime(this DateTime dateAndTime, bool includeTime) { // Format: January 26th, 2006 at 2:19pm string dateSuffix = "<sup>th</sup>"; switch (dateAndTime.Day) { case 1: case 21: case 31: dateSuffix = "<sup>st</sup>"; break; case 2: case 22: dateSuffix = "<sup>nd</sup>"; break; case 3: case 23: dateSuffix = "<sup>rd</sup>"; break; }
var dateFmt = String.Format("{0:MMMM} {1:%d}{2}, {3:yyyy} at {4:%h}:{5:mm}{6}", dateAndTime, dateAndTime, dateSuffix, dateAndTime, dateAndTime, dateAndTime, dateAndTime.ToString("tt").ToLower());
if (!includeTime) { dateFmt = String.Format("{0:MMMM} {1:%d}{2}, {3:yyyy}", dateAndTime, dateAndTime, dateSuffix, dateAndTime); }
return dateFmt; }
Usage:
DateTime.Now.ToFormattedDateTime(false) // Returns: December 19th, 2018
DateTime.Now.ToFormattedDateTime(true) // Returns: December 19th, 2018 at 9:00a
DateTime.ToW3CDate()
At one time, I wrote an application for a client where the date/time HAD to be in the W3C date (ISO 8601) standard when reporting (yes...the long one).
This is one of those extensions that's nice to have around instead of fiddling with a formatting string and it makes it simple enough to remember.
public static string ToW3CDate(this DateTime dt) { return dt.ToUniversalTime().ToString("s") + "Z"; }
Usage:
DateTime.Now.ToW3CDate(); // Returns: 1997-07-16T19:20:30.45Z
DateTime.GetQuarter()
Trying to figure out how to generate a report by quarter?
public static int GetQuarter(this DateTime fromDate) { return ((fromDate.Month - 1) / 3) + 1; }
Usage:
DateTime.Now.GetQuarter(); // Returns: 4
DirectoryInfo.Empty()
Ok, BIG WARNING here!
Yes, this will erase files and subdirectories. You have been warned!
public static void Empty(this System.IO.DirectoryInfo directory) { foreach (System.IO.FileInfo file in directory.GetFiles()) file.Delete(); foreach (System.IO.DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true); }
Usage:
DirectoryInfo di = new DirectoryInfo(@"c:\MyDir");
di.Empty(); // Files and Subdirectories wiped out...DOGS and CATS Living Together!
Object.ToDictionaryProperties(BindingFlags flags)
There are times when you just want a list of members and their values.
public static Dictionary<string, object> ToDictionaryProperties(this object atype, BindingFlags flags) { if (atype == null) return new Dictionary<string, object>(); var t = atype.GetType(); var props = t.GetProperties(flags); var dict = new Dictionary<string, object>(); foreach (PropertyInfo prp in props) { object value = prp.GetValue(atype, new object[] { }); dict.Add(prp.Name, value); } return dict; }
Usage:
var customerValues = customer.ToDictionaryProperties(BindingFlags.Public); // Returns: a list of public properties with their values in a Dictionary<string,object>()
DateTime.ToDaysTil(DateTime endDateTime)
Since we are coming up on Christmas, why not have a countdown version of the ToReadableTime() extension method. Have it focus on the future instead of telling us how long it's been since a date has passed?
This could also be used for a product launch ("15 days until the product launch").
public static string ToDaysTil(this DateTime value, DateTime endDateTime) { var ts = new TimeSpan(endDateTime.Ticks - value.Ticks); var delta = ts.TotalSeconds;
if (delta < 60) { return ts.Seconds == 1 ? "one second" : ts.Seconds + " seconds"; } if (delta < 120) { return "a minute"; } if (delta < 2700) // 45 * 60 { return ts.Minutes + " minutes"; } if (delta < 5400) // 90 * 60 { return "an hour"; } if (delta < 86400) // 24 * 60 * 60 { return ts.Hours + " hours"; } if (delta < 172800) // 48 * 60 * 60 { return "yesterday"; } if (delta < 2592000) // 30 * 24 * 60 * 60 { return ts.Days + " days"; } if (delta < 31104000) // 12 * 30 * 24 * 60 * 60 { int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30)); return months <= 1 ? "one month" : months + " months"; } var years = Convert.ToInt32(Math.Floor((double)ts.Days / 365)); return years <= 1 ? "one year" : years + " years"; }
Usage:
var christmas = new DateTime(2018, 12, 25);
var almost = DateTime.Now.ToDaysTil(christmas); // returns: "5 days" (you add what you want after it).
Object.IsNullOrDbNull()
This is great to test if objects are null or DBNull comes back from the database.
Again, it's about simplifying the code and making it readable.
public static bool IsNullOrDbNull(this object obj) { return obj == null || obj.GetType() == typeof(DBNull); }
Usage:
var notValid = obj.IsNullOrDbNull();
String.IsValidUrl()
This extension method was created to validate what a user was typing into a textbox.
How do you know whether a user entered a valid Url or not?
Of course, this doesn't hit the Url, it merely uses Regular Expressions to validate it.
public static bool IsValidUrl(this string text) { var rx = new Regex(@"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?"); return rx.IsMatch(text); }
Usage:
"https://www.danylkoweb.com/".IsValidUrl(); // returns: true
Conclusion
The whole idea behind extension methods is three-fold:
- Extend a class where you don't have access to the source code.
- Make your life easier when working with complex classes by using simple method calls.
- Allows the syntax to become readable for other developers.
I hope these extension methods make your holiday a little happier.
Merry Christmas, everyone and I'll see you next year (some I'll see at Codemash!).
Do you have a favorite extension method? Which class needs the most "extension?" Post your comments below and let's discuss!