0

I have written a C# extension method which currently works with an int. The code is simple - it determines if a given int starts with another int (without using string conversions) and returns either true or false:

namespace StartsWithNumberX
{
    public static class IntExtensions
    {
        /// <summary>
        /// Determine if the current number starts with another number.
        /// </summary>
        /// <param name="number"></param>
        /// <param name="startsWith"></param>
        /// <returns></returns>
        public static bool StartsWith(this int number, int startsWith)
        {
            var inputPlace = number.FindPlaceNumber();
            var comparePlace = startsWith.FindPlaceNumber();

            var placeDiff = inputPlace - comparePlace;

            var numberCopy = number;

            for (var i = 0; i < placeDiff; i++)
            {
                numberCopy = numberCopy/10;
            }

            return numberCopy == startsWith;
        }

        /// <summary>
        /// Find the "place" of the number. 
        /// less than 10 = 1 
        /// less than 100 = 2
        /// less than 1000 = 3 
        /// etc.
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        private static int FindPlaceNumber(this int number)
        {
            var placeNumber = 0;

            while (number > 0)
            {
                number = number/10;

                if (number > 0)
                {
                    placeNumber++;
                }
                else
                {
                    placeNumber++;
                    break;
                }
            }

            return placeNumber;
        }
    }
}

I want to make this code more generic so the same code will work with other numeric types say, long, double, decimal too.

Is it possible to do this in C#, or will I need to duplicate this code for the different number types?

Shar1er80
  • 9,001
  • 2
  • 20
  • 29
cda01
  • 1,278
  • 3
  • 14
  • 25
  • 2
    Why don't you share your code here,because maybe some country limit the internet,just like me :( – Sky Fang Jul 14 '15 at 00:54
  • Might be solved by this: http://stackoverflow.com/questions/1217591/c-adding-extension-methods-to-a-base-class-so-that-they-appear-in-derived-clas – Nitesh Patel Jul 14 '15 at 01:03
  • There is nothing like `where T: BaseTypes`, So I'll have to give bad news. Your best bet would be writing some overloads like `public static bool StartsWith(this long number, int startsWith) { return StartsWith((int)number, startsWith); }` – EZI Jul 14 '15 at 01:22
  • @EZI I believe that's what covariance/contravariance are for... https://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx – DanielS Jul 14 '15 at 01:50

2 Answers2

0

There is no generic type constraints for numbers, but there is a set of interfaces constraints you can ride on:

public static bool StartsWith<T>(this T number, T startsWith) where T :
        struct, 
        IComparable,
        IComparable<T>,
        IConvertible,
        IEquatable<T>,
        IFormattable
{
    if (typeof(int) != typeof(T) &&
        typeof(decimal) != typeof(T) &&
        typeof(float) != typeof(T) &&
        typeof(long) != typeof(T))
    {
        throw new ArgumentException(string.Format("The type {0} is not valid", typeof(T).Name));
    }

    // Do work

}
Eric
  • 5,675
  • 16
  • 24
-1

I have not found a solution to make your extension method more generic but I have an idea how it would make your code easier. Make a normal FindPlaceNumber-Method that accept a dynamic parameter

private static int _FindPlaceNumber(dynamic number)
    {
        var placeNumber = 0;

        while (number > 0)
        {
            number = number / 10;

            if (number > 0)
            {
                placeNumber++;
            }
            else
            {
                placeNumber++;
                break;
            }
        }

        return placeNumber;
    }

Then you can make three short extension methods, which call this mehthod like this.

 public static int FindPlaceNumber(this int number)
    {
        return _FindPlaceNumber(number);
    }
    public static int FindPlaceNumber(this double number)
    {
        return _FindPlaceNumber(number);
    }
    public static int FindPlaceNumber(this decimal number)
    {
        return _FindPlaceNumber(number);
    }

This is a fast option to make your extension method more "generic" without writing much code. The disadvantage of dynamic binding is, that it is slower than static typing.

Issa Jaber
  • 399
  • 2
  • 12