4
\$\begingroup\$

I got annoyed having to do things like string.IsNullOrEmpty(myString) when it seemed as if myString.IsNullOrEmpty() would perfectly suffice. Therefore, I wrote a small, simple library to wrap the static methods of primitives in extension methods.

I don't suppose there is much to critique about the code itself, as most methods are one-liners, but I'm wondering if what I have done violates any best-practice principles. Is there some insightful reasoning behind why these methods were left out in the first place?

The class dealing with strings is also very long, as I separated the classes based on which primitive they operated on, so all the Parse and TryParse methods belong to the string class. I also further wrapper the Parse methods, making private ParsePrimitive and public ToPrimitive methods. Is that an unnecessary layer of confusion?

CharExtensions.cs

using System.Globalization;

namespace PrimitiveExtensions
{
    public static class CharExtensions
    {
        public static double GetNumericValue(this char c)
        {
            return char.GetNumericValue(c);
        }

        public static UnicodeCategory GetUnicodeCategory(this char c)
        {
            return char.GetUnicodeCategory(c);
        }

        public static bool IsControl(this char c)
        {
            return char.IsControl(c);
        }

        public static bool IsDigit(this char c)
        {
            return char.IsDigit(c);
        }

        public static bool IsHighSurrogate(this char c)
        {
            return char.IsHighSurrogate(c);
        }

        public static bool IsLetter(this char c)
        {
            return char.IsLetter(c);
        }

        public static bool IsLetterOrDigit(this char c)
        {
            return char.IsLetterOrDigit(c);
        }

        public static bool IsLower(this char c)
        {
            return char.IsLower(c);
        }

        public static bool IsLowSurrogate(this char c)
        {
            return char.IsLowSurrogate(c);
        }

        public static bool IsNumber(this char c)
        {
            return char.IsNumber(c);
        }

        public static bool IsPunctuation(this char c)
        {
            return char.IsPunctuation(c);
        }

        public static bool IsSeparator(this char c)
        {
            return char.IsSeparator(c);
        }

        public static bool IsSurrogate(this char c)
        {
            return char.IsSurrogate(c);
        }

        public static bool IsSymbol(this char c)
        {
            return char.IsSymbol(c);
        }

        public static bool IsUpper(this char c)
        {
            return char.IsUpper(c);
        }

        public static bool IsWhiteSpace(this char c)
        {
            return char.IsWhiteSpace(c);
        }

        public static char ToLower(this char c)
        {
            return char.ToLower(c);
        }

        public static char ToLower(this char c, CultureInfo culture)
        {
            return char.ToLower(c, culture);
        }

        public static char ToLowerInvariant(this char c)
        {
            return char.ToLowerInvariant(c);
        }

        public static char ToUpper(this char c)
        {
            return char.ToUpper(c);
        }

        public static char ToUpper(this char c, CultureInfo culture)
        {
            return char.ToUpper(c, culture);
        }

        public static char ToUpperInvariant(this char c)
        {
            return char.ToUpper(c);
        }
    }
}

DoubleExtensions.cs

namespace PrimitiveExtensions
{
    public static class DoubleExtensions
    {
        public static bool IsInfinity(this double d)
        {
            return double.IsInfinity(d);
        }

        public static bool IsNaN(this double d)
        {
            return double.IsNaN(d);
        }

        public static bool IsNegativeInfinity(this double d)
        {
            return double.IsNegativeInfinity(d);
        }

        public static bool IsPositiveInfinity(this double d)
        {
            return double.IsPositiveInfinity(d);
        }
    }
}

FloatExtensions.cs

namespace PrimitiveExtensions
{
    public static class FloatExtensions
    {
        public static bool IsInfinity(this float f)
        {
            return float.IsInfinity(f);
        }

        public static bool IsNaN(this float f)
        {
            return float.IsNaN(f);
        }

        public static bool IsNegativeInfinity(this float f)
        {
            return float.IsNegativeInfinity(f);
        }

        public static bool IsPositiveInfinity(this float f)
        {
            return float.IsPositiveInfinity(f);
        }
    }
}

StringExtensions.cs

using System;
using System.Globalization;

namespace PrimitiveExtensions
{
    public static class StringExtensions
    {
        public static int Compare(this string s1, string s2)
        {
            return string.Compare(s1, s2);
        }

        public static int Compare(this string s1, string s2, bool ignoreCase)
        {
            return string.Compare(s1, s2, ignoreCase);
        }

        public static int Compare(
            this string s1, string s2, bool ignoreCase, CultureInfo culture)
        {
            return string.Compare(s1, s2, ignoreCase, culture);
        }

        public static int Compare(
            this string s1,
            string s2,
            CultureInfo culture,
            CompareOptions options)
        {
            return string.Compare(s1, s2, culture, options);
        }

        public static int Compare(
            this string s1, string s2, StringComparison comparisonType)
        {
            return string.Compare(s1, s2, comparisonType);
        }

        public static int CompareOrdinal(this string s1, string s2)
        {
            return string.CompareOrdinal(s1, s2);
        }

        public static int ConvertToUtf32(this string s, int index)
        {
            return char.ConvertToUtf32(s, index);
        }

        public static string Copy(this string s)
        {
            return string.Copy(s);
        }

        public static bool EqualsCurrentCulture(this string s1, string s2)
        {
            return s1.Equals(s2, StringComparison.CurrentCulture);
        }

        public static bool EqualsCurrentCultureIgnoreCase(
            this string s1, string s2)
        {
            return s1.Equals(s2, StringComparison.CurrentCultureIgnoreCase);
        }

        public static bool EqualsInvariantCulture(this string s1, string s2)
        {
            return s1.Equals(s2, StringComparison.InvariantCulture);
        }

        public static bool EqualsInvariantCultureIgnoreCase(
            this string s1, string s2)
        {
            return s1.Equals(s2, StringComparison.InvariantCultureIgnoreCase);
        }

        public static bool EqualsOrdinal(this string s1, string s2)
        {
            return s1.Equals(s2, StringComparison.Ordinal);
        }

        public static bool EqualsOrdinalIgnoreCase(this string s1, string s2)
        {
            return s1.Equals(s2, StringComparison.OrdinalIgnoreCase);
        }

        public static double GetNumericValue(this string s, int index)
        {
            return char.GetNumericValue(s, index);
        }

        public static UnicodeCategory GetUnicodeCategory(
            this string s, int index)
        {
            return char.GetUnicodeCategory(s, index);
        }

        public static bool IsControl(this string s, int index)
        {
            return char.IsControl(s, index);
        }

        public static bool IsDigit(this string s, int index)
        {
            return char.IsDigit(s, index);
        }

        public static bool IsHighSurrogate(this string s, int index)
        {
            return char.IsHighSurrogate(s, index);
        }

        public static bool IsLetter(this string s, int index)
        {
            return char.IsLetter(s, index);
        }

        public static bool IsLetterOrDigit(this string s, int index)
        {
            return char.IsLetterOrDigit(s, index);
        }

        public static bool IsLower(this string s, int index)
        {
            return char.IsLower(s, index);
        }

        public static bool IsLowSurrogate(this string s, int index)
        {
            return char.IsLowSurrogate(s, index);
        }

        public static bool IsNullOrEmpty(this string s)
        {
            return string.IsNullOrEmpty(s);
        }

        public static bool IsNullOrWhiteSpace(this string s)
        {
            return string.IsNullOrWhiteSpace(s);
        }

        public static bool IsNumber(this string s, int index)
        {
            return char.IsNumber(s, index);
        }

        public static bool IsPunctuation(this string s, int index)
        {
            return char.IsPunctuation(s, index);
        }

        public static bool IsSeparator(this string s, int index)
        {
            return char.IsSeparator(s, index);
        }

        public static bool IsSurrogate(this string s, int index)
        {
            return char.IsSurrogate(s, index);
        }

        public static bool IsSurrogatePair(this string s, int index)
        {
            return char.IsSurrogatePair(s, index);
        }

        public static bool IsSymbol(this string s, int index)
        {
            return char.IsSymbol(s, index);
        }

        public static bool IsUpper(this string s, int index)
        {
            return char.IsUpper(s, index);
        }

        public static bool IsWhiteSpace(this string s, int index)
        {
            return char.IsWhiteSpace(s, index);
        }

        public static bool IsWhiteSpace(this string s)
        {
            foreach (var c in s)
            {
                if (!c.IsWhiteSpace())
                {
                    return false;
                }
            }

            return true;
        }

        public static bool ToBool(this string s)
        {
            return s.ParseBool();
        }

        public static byte ToByte(this string s)
        {
            return s.ParseByte();
        }

        public static byte ToByte(this string s, IFormatProvider provider)
        {
            return s.ParseByte(provider);
        }

        public static byte ToByte(this string s, NumberStyles style)
        {
            return s.ParseByte(style);
        }

        public static byte ToByte(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return s.ParseByte(style, provider);
        }

        public static char ToChar(this string s)
        {
            return s.ParseChar();
        }

        public static DateTime ToDateTime(this string s)
        {
            return s.ParseDateTime();
        }

        public static DateTime ToDateTime(
            this string s, IFormatProvider provider)
        {
            return s.ParseDateTime(provider);
        }

        public static DateTime ToDateTime(
            this string s, IFormatProvider provider, DateTimeStyles style)
        {
            return s.ParseDateTime(provider, style);
        }

        public static DateTime ToDateTime(
            this string s, string format, IFormatProvider provider)
        {
            return s.ParseExactDateTime(format, provider);
        }

        public static decimal ToDecimal(this string s)
        {
            return s.ParseDecimal();
        }

        public static decimal ToDecimal(
            this string s, IFormatProvider provider)
        {
            return s.ParseDecimal(provider);
        }

        public static decimal ToDecimal(this string s, NumberStyles style)
        {
            return s.ParseDecimal(style);
        }

        public static decimal ToDecimal(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return s.ParseDecimal(style, provider);
        }

        public static double ToDouble(this string s)
        {
            return s.ParseDouble();
        }

        public static double ToDouble(this string s, IFormatProvider provider)
        {
            return s.ParseDouble(provider);
        }

        public static double ToDouble(this string s, NumberStyles style)
        {
            return s.ParseDouble(style);
        }

        public static double ToDouble(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return s.ParseDouble(style, provider);
        }

        public static float ToFloat(this string s)
        {
            return float.Parse(s);
        }

        public static float ToFloat(this string s, NumberStyles style)
        {
            return s.ParseFloat(style);
        }

        public static float ToFloat(this string s, IFormatProvider provider)
        {
            return s.ParseFloat(provider);
        }

        public static float ToFloat(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return s.ParseFloat(style, provider);
        }

        public static int ToInt(this string s)
        {
            return s.ParseInt();
        }

        public static int ToInt(this string s, NumberStyles style)
        {
            return s.ParseInt(style);
        }

        public static int ToInt(this string s, IFormatProvider provider)
        {
            return s.ParseInt(provider);
        }

        public static int ToInt(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return s.ParseInt(style, provider);
        }

        public static long ToLong(this string s)
        {
            return s.ParseLong();
        }

        public static long ToLong(this string s, NumberStyles style)
        {
            return s.ParseLong(style);
        }

        public static long ToLong(this string s, IFormatProvider provider)
        {
            return s.ParseLong(provider);
        }

        public static long ToLong(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return s.ParseLong(style, provider);
        }

        public static short ToShort(this string s)
        {
            return s.ParseShort();
        }

        public static short ToShort(this string s, IFormatProvider provider)
        {
            return s.ParseShort(provider);
        }

        public static short ToShort(this string s, NumberStyles style)
        {
            return s.ParseShort(style);
        }

        public static short ToShort(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return s.ParseShort(style, provider);
        }

        public static bool TryParse(this string s, out int result)
        {
            return int.TryParse(s, out result);
        }

        public static bool TryParse(
            this string s,
            NumberStyles style,
            IFormatProvider provider,
            out int result)
        {
            return int.TryParse(s, style, provider, out result);
        }

        public static bool TryParse(this string s, out double result)
        {
            return double.TryParse(s, out result);
        }

        public static bool TryParse(
            this string s,
            NumberStyles style,
            IFormatProvider provider,
            out double result)
        {
            return double.TryParse(s, style, provider, out result);
        }

        public static bool TryParse(this string s, out byte result)
        {
            return byte.TryParse(s, out result);
        }

        public static bool TryParse(
            this string s,
            NumberStyles style,
            IFormatProvider provider,
            out byte result)
        {
            return byte.TryParse(s, style, provider, out result);
        }

        public static bool TryParse(this string s, out bool result)
        {
            return bool.TryParse(s, out result);
        }

        public static bool TryParse(this string s, out char result)
        {
            return char.TryParse(s, out result);
        }

        public static bool TryParse(this string s, out DateTime result)
        {
            return DateTime.TryParse(s, out result);
        }

        public static bool TryParse(
            this string s,
            IFormatProvider provider,
            DateTimeStyles style,
            out DateTime result)
        {
            return DateTime.TryParse(s, provider, style, out result);
        }

        public static bool TryParse(
            this string s,
            string format,
            IFormatProvider provider,
            DateTimeStyles style,
            out DateTime result)
        {
            return DateTime.TryParseExact(
                s, format, provider, style, out result);
        }

        public static bool TryParse(
            this string s,
            string[] formats,
            IFormatProvider provider,
            DateTimeStyles style,
            out DateTime result)
        {
            return DateTime.TryParseExact(
                s, formats, provider, style, out result);
        }

        public static bool TryParse(this string s, out decimal result)
        {
            return decimal.TryParse(s, out result);
        }

        public static bool TryParse(
            this string s,
            NumberStyles style,
            IFormatProvider provider,
            out decimal result)
        {
            return decimal.TryParse(s, style, provider, out result);
        }

        public static bool TryParse(this string s, out short result)
        {
            return short.TryParse(s, out result);
        }

        public static bool TryParse(
            this string s,
            NumberStyles style,
            IFormatProvider provider,
            out short result)
        {
            return short.TryParse(s, style, provider, out result);
        }

        public static bool TryParse(this string s, out long result)
        {
            return long.TryParse(s, out result);
        }

        public static bool TryParse(
            this string s,
            NumberStyles style,
            IFormatProvider provider,
            out long result)
        {
            return long.TryParse(s, style, provider, out result);
        }

        public static bool TryParse(this string s, out float result)
        {
            return float.TryParse(s, out result);
        }

        public static bool TryParse(
            this string s,
            NumberStyles style,
            IFormatProvider provider,
            out float result)
        {
            return float.TryParse(s, style, provider, out result);
        }

        private static bool ParseBool(this string s)
        {
            return bool.Parse(s);
        }

        private static byte ParseByte(this string s)
        {
            return byte.Parse(s);
        }

        private static byte ParseByte(this string s, IFormatProvider provider)
        {
            return byte.Parse(s, provider);
        }

        private static byte ParseByte(this string s, NumberStyles style)
        {
            return byte.Parse(s, style);
        }

        private static byte ParseByte(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return byte.Parse(s, style, provider);
        }

        private static char ParseChar(this string s)
        {
            return char.Parse(s);
        }

        private static DateTime ParseDateTime(this string s)
        {
            return DateTime.Parse(s);
        }

        private static DateTime ParseDateTime(
            this string s, IFormatProvider provider)
        {
            return DateTime.Parse(s, provider);
        }

        private static DateTime ParseDateTime(
            this string s, IFormatProvider provider, DateTimeStyles style)
        {
            return DateTime.Parse(s, provider, style);
        }

        private static decimal ParseDecimal(this string s)
        {
            return decimal.Parse(s);
        }

        private static decimal ParseDecimal(
            this string s, IFormatProvider provider)
        {
            return decimal.Parse(s, provider);
        }

        private static decimal ParseDecimal(this string s, NumberStyles style)
        {
            return decimal.Parse(s, style);
        }

        private static decimal ParseDecimal(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return decimal.Parse(s, style, provider);
        }

        private static double ParseDouble(this string s)
        {
            return double.Parse(s);
        }

        private static double ParseDouble(
            this string s, IFormatProvider provider)
        {
            return double.Parse(s, provider);
        }

        private static double ParseDouble(this string s, NumberStyles style)
        {
            return double.Parse(s, style);
        }

        private static double ParseDouble(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return double.Parse(s, style, provider);
        }

        private static DateTime ParseExactDateTime(
            this string s, string format, IFormatProvider provider)
        {
            return DateTime.ParseExact(s, format, provider);
        }

        private static DateTime ParseExactDateTime(
            this string s,
            string format,
            IFormatProvider provider,
            DateTimeStyles style)
        {
            return DateTime.ParseExact(s, format, provider, style);
        }

        private static DateTime ParseExactDateTime(
            this string s,
            string[] formats,
            IFormatProvider provider,
            DateTimeStyles style)
        {
            return DateTime.ParseExact(s, formats, provider, style);
        }

        private static float ParseFloat(this string s)
        {
            return float.Parse(s);
        }

        private static float ParseFloat(this string s, IFormatProvider provider)
        {
            return float.Parse(s, provider);
        }

        private static float ParseFloat(this string s, NumberStyles style)
        {
            return float.Parse(s, style);
        }

        private static float ParseFloat(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return float.Parse(s, style, provider);
        }

        private static int ParseInt(this string s)
        {
            return int.Parse(s);
        }

        private static int ParseInt(this string s, IFormatProvider provider)
        {
            return int.Parse(s, provider);
        }

        private static int ParseInt(this string s, NumberStyles style)
        {
            return int.Parse(s, style);
        }

        private static int ParseInt(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return int.Parse(s, style, provider);
        }

        private static long ParseLong(this string s)
        {
            return long.Parse(s);
        }

        private static long ParseLong(this string s, IFormatProvider provider)
        {
            return long.Parse(s, provider);
        }

        private static long ParseLong(this string s, NumberStyles style)
        {
            return long.Parse(s, style);
        }

        private static long ParseLong(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return long.Parse(s, style, provider);
        }

        private static short ParseShort(this string s)
        {
            return short.Parse(s);
        }

        private static short ParseShort(this string s, IFormatProvider provider)
        {
            return short.Parse(s, provider);
        }

        private static short ParseShort(this string s, NumberStyles style)
        {
            return short.Parse(s, style);
        }

        private static short ParseShort(
            this string s, NumberStyles style, IFormatProvider provider)
        {
            return short.Parse(s, style, provider);
        }
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ You are not reinventing the wheel, but standing on the shoulders of .Net Framework. \$\endgroup\$ – Xiaoy312 Jun 13 '16 at 18:11
  • \$\begingroup\$ It would be nice if the FloatExtensions and DoubleExtensions could handle nullables. \$\endgroup\$ – JanDotNet Jun 13 '16 at 18:46
  • \$\begingroup\$ I believe you are firmly on the path toward a more functional style using Extension Methods. There's a lot of really positive things about going functional. For one thing you create classes that focus on only one thing. 2nd they are usually very small in nature and don't keep state. If we continue the concept you've shown above in almost everything we do, then we build these massive reusable Function libraries. They allow us to code faster than we can today, we become users of out toolbox and keep adding tools as we go! \$\endgroup\$ – John Peters Jun 13 '16 at 22:07
  • \$\begingroup\$ Why were these left out to begin with? Easy, they were all written long before extension methods were introduced into the language. \$\endgroup\$ – RubberDuck Jun 13 '16 at 23:57
5
\$\begingroup\$

I would probably go to jail for this :)

using static StringTest;
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Test" == NullOrEmpty);
        Console.WriteLine("" == NullOrWhiteSpace);
        Console.WriteLine(null == NullOrWhiteSpace);
    }
}

Where:

class StringTest
{
    public static readonly StringTest NullOrEmpty = new StringTest(d => string.IsNullOrEmpty(d));
    public static readonly StringTest NullOrWhiteSpace = new StringTest(d => string.IsNullOrWhiteSpace(d));

    public StringTest(Predicate<string> predicate)
    {
        Predicate = predicate;
    }

    Predicate<string> Predicate { get; }

    public static bool operator==(StringTest left, string right) =>
        left.Predicate(right);

    public static bool operator==(string left, StringTest right) =>
        right.Predicate(left);

    public static bool operator!=(StringTest left, string right) =>
        !left.Predicate(right);

    public static bool operator!=(string left, StringTest right) =>
        !right.Predicate(left);
}
\$\endgroup\$
  • 1
    \$\begingroup\$ You could just write new StringTest(string.IsNullOrEmpty), asstring.IsNullOrEmpty can be implicitly converted into a Predicate<string>. \$\endgroup\$ – Xiaoy312 Jun 13 '16 at 20:38
  • 2
    \$\begingroup\$ I'm sorry, but I'm not following. Could you provide a little bit of a explanation/summary? \$\endgroup\$ – Michael Brandon Morris Jun 13 '16 at 23:59
  • 1
    \$\begingroup\$ @MichaelBrandonMorris We can not do two checks using one equality operator, usually we need two: text == null || text == "". The solution above allows you to use a pseudo constant NullOrEmpty to check both conditions at once. It violates syntax rules of the language, so looks like a crime :) \$\endgroup\$ – Dmitry Nogin Jun 14 '16 at 0:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.