Skip to content

15 Helpful .NET Extension Methods to Increase Productivity

Alright folks, this is my arsenal of useful Extension Methods for .NET 3.0+ mostly written by me to help with development productivity.

Some real time-savers in here such as .ToInt() and .ToDateTime() (with and without a default fallback value), plus a simple RegEx matcher thrown into the mix and my CloneProperties method I wrote yesterday.

Included namespaces are:

  • StringExtensions;
  • NullableBooleanExtensions;
  • ObjectExtensions;
  • ValidatorExtensions and;
  • Updated 18-Feb-2009: HtmlHelperExtensions! (How could I forget these guys)


I mean you can go on forever with every possible combination, but these are the few I’ve found need for the most.

Once you’ve included the code below, a simple namespace reference is all you need and away you go.

namespace Application.Business.Utility
{
    public static class StringExtension
    {
        ///

        /// Convert to Integer specifying a default value.
        /// 

        ///

        ///

        /// 
        public static int ToInt(this string str, int defaultValue)
        {
            int res;
            if (!string.IsNullOrEmpty(str))
                return int.TryParse(str, out res) ? res : defaultValue;
            else
                return defaultValue;
        }

        ///

        /// Convert to Integer.
        /// 

        ///

        /// 
        public static int ToInt(this string str)
        {
            int res;
            try
            {
                if (!string.IsNullOrEmpty(str))
                    res = int.Parse(str);
                else
                    res = 0;
            }
            catch (OverflowException)
            {
                throw;
            }
            catch (Exception)
            {
                res = 0;
            }
            return res;
        }

        ///

        /// Convert to Long specifying a default value.
        /// 

        ///

        ///

        /// 
        public static long ToLng(this string str, long defaultValue)
        {
            long res;
            try
            {
                if (!string.IsNullOrEmpty(str))
                    res = long.Parse(str);
                else
                    res = defaultValue;
            }
            catch (OverflowException)
            {
                throw;
            }
            catch (Exception)
            {
                res = defaultValue;
            }
            return res;
        }

        ///

        /// Convert to Long.
        /// 

        ///

        /// 
        public static long ToLng(this string str)
        {
            long res;
            if (!string.IsNullOrEmpty(str))
                return long.TryParse(str, out res) ? res : 0;
            else
                return 0;
        }

        ///

        /// Convert to Decimal specifying a default value.
        /// 

        ///

        ///

        /// 
        public static decimal ToDec(this string str, decimal defaultValue)
        {
            decimal res;
            if (!string.IsNullOrEmpty(str))
                return decimal.TryParse(str, out res) ? res : defaultValue;
            else
                return defaultValue;
        }

        ///

        /// Convert to Decimal.
        /// 

        ///

        /// 
        public static decimal ToDec(this string str)
        {
            decimal res;
            if (!string.IsNullOrEmpty(str))
                return decimal.TryParse(str, out res) ? res : 0;
            else
                return 0;
        }

        ///

        /// Convert to Boolean specifying a default value.
        /// 

        ///

        ///

        /// 
        public static bool ToBool(this string str, bool defaultValue)
        {
            bool res;
            if (!string.IsNullOrEmpty(str))
                return bool.TryParse(str, out res) ? res : defaultValue;
            else
                return false;
        }

        ///

        /// Convert to Boolean.
        /// 

        ///

        /// 
        public static bool ToBool(this string str)
        {
            bool res;
            if (!string.IsNullOrEmpty(str))
                return bool.TryParse(str, out res) ? res : false;
            else
                return false;
        }

        ///

        /// Convert to DateTime specifying a default value.
        /// 

        ///

        ///

        /// 
        public static DateTime ToDateTime(this string str, DateTime defaultValue)
        {
            DateTime res;
            if (!string.IsNullOrEmpty(str))
                return DateTime.TryParse(str, out res) ? res : defaultValue;
            else
                return DateTime.MinValue;
        }

        ///

        /// Convert to DateTime.
        /// 

        ///

        /// 
        public static DateTime ToDateTime(this string str)
        {
            DateTime res;
            if (!string.IsNullOrEmpty(str))
                return DateTime.TryParse(str, out res) ? res : DateTime.MinValue;
            else
                return DateTime.MinValue;
        }

        ///

        /// Indicates whether the regular expression finds a match in the input string using the regular expression specified in the pattern parameter.
        /// 

        ///
String to match
        ///
Regular expression, eg. [a-Z]{3}
        ///
Return true only if string was matched entirely
        /// 
        public static bool IsMatch(this string value, string regularExpression, bool matchEntirely)
        {
            return Regex.IsMatch(value, matchEntirely ? "\\A" + regularExpression + "\\z" : regularExpression);
        }

    }

    public static class NullableBooleanExtension
    {
        ///

        /// Convert to Integer specifying a default value.
        /// 

        ///

        ///

        /// 
        public static int ToInt(this bool? value, int defaultValue)
        {
            int res;
            try
            {
                res = value.HasValue ? Convert.ToInt32(value) : defaultValue;
            }
            catch (Exception)
            {
                res = defaultValue;
            }
            return res;
        }

        ///

        /// Convert to Integer.
        /// 

        ///

        /// 
        public static int ToInt(this bool? value)
        {
            int res;
            try
            {
                res = value.HasValue ? Convert.ToInt32(value) : 0;
            }
            catch (Exception)
            {
                res = 0;
            }
            return res;
        }

    }

    public static class ObjectExtension
    {
        ///

        /// Clone properties from an original object to a destination object.
        /// 

        /// 
        /// 
        ///

        ///

        public static void CloneProperties(this T1 origin, T2 destination)
        {
            // Instantiate if necessary
            if (destination == null) throw new ArgumentNullException("destination", "Destination object must first be instantiated.");
            // Loop through each property in the destination
            foreach (var destinationProperty in destination.GetType().GetProperties())
            {
                // find and set val if we can find a matching property name and matching type in the origin with the origin's value
                if (origin != null && destinationProperty.CanWrite)
                {
                    origin.GetType().GetProperties().Where(x => x.CanRead && (x.Name == destinationProperty.Name && x.PropertyType == destinationProperty.PropertyType))
                        .ToList()
                        .ForEach(x => destinationProperty.SetValue(destination, x.GetValue(origin, null), null));
                }
            }
        }
    }

    public static class ValidatorExtension
    {
        ///

        /// Return true if value is between a range of values.
        /// 

        /// 
        public static bool Between(this int value, int start, int end, bool inclusive)
        {
            if (inclusive)
                return (value >= start && value <= end) ? true : false;
            return (value > start && value < end) ? true : false;
        }

    }

    public static class HtmlHelperExtensions
    {
        #region HtmlHelper extensions

        ///

        /// Format date/time object into html representation of 'relative time' format, eg. "5 seconds ago".
        /// 

        ///

        ///

        /// 
        public static string FormatDateTimeRelative(this HtmlHelper htmlHelper, DateTime? value)
        {
            if (value.HasValue)
            {
                // As suggested on stackoverflow.com and found to be the most comprehensive method.
                // http://stackoverflow.com/questions/11/how-do-i-calculate-relative-time

                TimeSpan oSpan = DateTime.Now.Subtract(value.Value);
                double TotalMinutes = oSpan.TotalMinutes;
                string Suffix = " ago";

                if (TotalMinutes < 0.0)
                {
                    TotalMinutes = Math.Abs(TotalMinutes);
                    Suffix = " from now";
                }

                Dictionary> aValue = new Dictionary>();
                aValue.Add(0.75, () => "less than a minute");
                aValue.Add(1.5, () => "about a minute");
                aValue.Add(45, () => string.Format("{0} minutes", Math.Round(TotalMinutes)));
                aValue.Add(90, () => "about an hour");
                aValue.Add(1440, () => string.Format("about {0} hours", Math.Round(Math.Abs(oSpan.TotalHours)))); // 60 * 24
                aValue.Add(2880, () => "a day"); // 60 * 48
                aValue.Add(43200, () => string.Format("{0} days", Math.Floor(Math.Abs(oSpan.TotalDays)))); // 60 * 24 * 30
                aValue.Add(86400, () => "about a month"); // 60 * 24 * 60
                aValue.Add(525600, () => string.Format("{0} months", Math.Floor(Math.Abs(oSpan.TotalDays / 30)))); // 60 * 24 * 365
                aValue.Add(1051200, () => "about a year"); // 60 * 24 * 365 * 2
                aValue.Add(double.MaxValue, () => string.Format("{0} years", Math.Floor(Math.Abs(oSpan.TotalDays / 365))));

                return aValue.First(n => TotalMinutes < n.Key).Value.Invoke() + Suffix;
            }
            return string.Empty;
        }

        ///

        /// Truncate text by given input to 40 characters with trailing ellipsis.
        /// 

        ///

        ///

        /// 
        public static string Truncate(this HtmlHelper htmlHelper, string text)
        {
            if (!string.IsNullOrEmpty(text))
                return text.Length > 40 ? text.Substring(0, 40) + "…" : text;
            return string.Empty;
        }

        #endregion
    }
}
VN:F [1.9.1_1087]
Rating: 4.0/5 (1 vote cast)
VN:F [1.9.1_1087]
Rating: 0 (from 0 votes)
15 Helpful .NET Extension Methods to Increase Productivity, 4.0 out of 5 based on 1 rating
Bookmark and Share
kick it on DotNetKicks.com
Shout it

NOW, FOR A WORD FROM OUR SPONSORS

17 Comments

  1. redsquare

    No FormatWith?

    ExtensionOverflow has a more comphrensive lib of extension methods.

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 12:37 am | Permalink
  2. Rob Packwood

    I am curious to see what others say on the usefulness of the conversion extension methods and how dangerous they may be to other developers.

    On the ValidatorExtension, you could change it to be an IComparableExtension where instead of extending an int you extend IComparable to take something like this (apologies for the formatting here):

    public static bool IsBetween( this T inputValue, T minValue, T maxValue ) where T : IComparable
    {
    return inputValue.CompareTo( minValue ) >= 0 &&
    inputValue.CompareTo( maxValue ) <= 0;
    }

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 12:51 am | Permalink
  3. Rob Packwood

    On my last post the IsBetween method did take a generic type parameter, but it did not make it on the final comment.

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 12:52 am | Permalink
  4. Chris

    So, when ToInt() causes an OutOfMemoryException or a ExecutionEngineException or whatnot, it results to 0. Probably, especially for general purpose methods, you should use more specific catch-blocks.

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 3:12 am | Permalink
  5. Great article.

    I find the combination of extension methods and generics to be both elegant and timesaving:

    public static Nullable ToNullable(this object o)
    where T : struct
    {
    return (o != null && o != DBNull.Value) ? (Nullable)o : null;
    }

    public static T ToDefaultable(this object o)
    where T : struct
    {
    return (o != null && o != DBNull.Value) ? (T)o : default(T);
    }

    What do you think?

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 3:20 am | Permalink
  6. My generic parameters got lost. Let me try again…

    public static Nullable<T> ToNullable<T>(this object o)
    where T : struct
    {
    return (o != null && o != DBNull.Value) ? (Nullable<T>)o : null;
    }

    public static T ToDefaultable<T>(this object o)
    where T : struct
    {
    return (o != null && o != DBNull.Value) ? (T)o : default(T);
    }

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 3:21 am | Permalink
  7. I’ve been there myself as well. Just discovered extension methods, and creating a .ToInt() on string, or perhaps even on object itself would be a major productivity gain.

    However, I really dislike it. String should not have a ToInt() method as it’s only a very small subset of all strings that can actually be converted to ints, and intellisense won’t help you notice the difference – only your application code will. Having a ToInt (my ramblings concern all of the methods, not just ToInt) will nurture you into writing bad code, not thinking enough about where to convert what.

    I’d much rather write Convert.ToInt32() the relatively few places I do a convert. For the QueryString (or Form – can’t see which you’re referring), I’ve got a generic QueryStringHelper object that’ll do the conversions for me:
    QueryStringHelper.To(“moduleid”);

    That makes conversions easier on the eye (imho) and contains the logic where it belongs – away from the string object.

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 5:50 am | Permalink
  8. steve

    Not sure I see the benefit of calling a method ToLng. Why not ToLong, since that’s what it is doing. Oh, right, you would have to type that extra character…

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 8:39 am | Permalink
  9. Graham O'Neale

    @redsquare: Wow, cool redsquare. Thanks for sharing the link. Hadn’t seen this.

    @Rob Packwood: Nice, looks like a great generic implementation for IsBetween().

    @Chris: Perhaps. This was merely a collection of methods I’ve found useful over time and haven’t really looked back on them too much – I’ve never encountered these exceptions so I guess never thought on how they could be improved!

    @Robert Hanlon: That’s kinda cool Rob, so it will convert anything to a Nullable type?

    @Mark Rasmussen: Yes I see where you’re coming from Mark, but I don’t think there is a reason to dislike it. When I say that, it is from my perspective and my disciplines, I would use it intentionally as a “convenience” to Convert.ToInt32() and it should be no less thought out than if you were to use the original convert method. I’ve been working with a lot of legacy systems of late, cutting up files and such, so I have found the ToInt() method personally incredibly useful with what I needed to do.

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 8:50 am | Permalink
  10. Graham O'Neale

    I completely forgot about my HtmlHelperExtensions which were stored in another file! I have just updated my samples.

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 8:58 am | Permalink
  11. Graham O'Neale

    @Steve: You bet. That would be horrible. No really because I am a consistency freak and I think I just wanted them all three characters. But then I ruined it with ToBool & ToDateTime anyway….

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 9:36 am | Permalink
  12. Graham, no, my ToNullable method converts things cast as object to the Nullable<> form of some value type (int, double, bool, and DateTime get the most mileage). The compiler checks that these are value types with the “where T : struct” constraint. Reference types, including string, don’t need ToNullable, because those variables can already be set to null.

    It’s most effective when reading from the database:

    int? imageKey = row["imagekey"].ToNullable();

    (…where “row” is a DataRow, natch.)

    It essentially replaces this code:
    int? imageKey;
    if (row["imagekey"] == null) imageKey = null;
    else imageKey = (int)row["imageKey"];

    It doesn’t solve any groundbreaking problems, but it does clean code up, which is what I find extension methods are best at.

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 9:46 am | Permalink
  13. Graham O'Neale

    @Robert: Sorry, I said anything because I saw the object type input, but the “where T : struct” constraint I understand, nice, as all value types derive from a struct and as you say ref types do not need to be changed. Very cool.

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 18-Feb-09 at 10:02 am | Permalink
  14. Peter Parker

    Did I miss something? Where are the downloads? I don’t see how I can get your code?! :-/ Please help.

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 21-Feb-09 at 6:50 pm | Permalink
  15. Why, in ToInt(defaultValue), does a null or empty string convert to 0 instead of defaultValue?

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 24-Feb-09 at 8:03 am | Permalink
  16. Graham O'Neale

    @Peter: the code should have loaded on the page in source code formatting? Do you see the scrollable div?

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 24-Feb-09 at 8:45 am | Permalink
  17. Graham O'Neale

    @James: It shouldn’t. This has been fixed. Cheers dude.

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
    Posted on 24-Feb-09 at 8:59 am | Permalink

3 Trackbacks/Pingbacks

  1. DotNetShoutout on 17-Feb-09 at 1:00 pm

    15 Helpful .NET Extension Methods to Increase Productivity « {Programming} & Life…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

    VA:F [1.9.1_1087]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.1_1087]
    Rating: 0 (from 0 votes)
  2. [...] 15 Helpful .NET Extension Methods to Increase Productivity « {Programming} & Life. Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages. [...]

  3. [...] (Dan Fernandez and Brian Keller), I really appreciate the video review regarding my post “15 Helpful .NET Extension Methods to Increase Productivity” and the plug to my website! The extension methods were nothing [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*
My name is Graham O'Neale and I'm a software architect from Gold Coast, Australia. I am an overtime thinker, full time coder and awake part time in the real world. I have a keen interest in software development, particularly in the realm of programming (C#, ASP.NET, ASP.NET MVC, LINQ (2 SQL), Entity Framework, Silverlight, Blend, WCF, WPF) and a keen interest in the cutting edge and innovation. I have a new found love for design patterns, ALT.NET practices and well crafted software architecture. The purpose of this blog is to express any thoughts, findings, tips and gripes along my travels in the wonderful world of coding and technology...