简体   繁体   中英

Generic extension method in C#

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?

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.

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

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM