【问题标题】:Generic extension method in C#C#中的通用扩展方法
【发布时间】:2015-10-02 10:57:37
【问题描述】:

我编写了一个 C# 扩展方法,该方法目前适用于 int。代码很简单 - 它确定给定的 int 是否以另一个 int 开头(不使用字符串转换)并返回 true 或 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;
        }
    }
}

我想让这段代码更通用,这样同样的代码也可以用于其他数字类型,比如longdoubledecimal

是否可以在 C# 中执行此操作,或者我需要为不同的数字类型复制此代码?

【问题讨论】:

  • 你为什么不在这里分享你的代码,因为也许有些国家限制互联网,就像我一样:(
  • 没有像where T: BaseTypes 这样的东西,所以我不得不给出一个坏消息。您最好的选择是编写一些重载,例如 public static bool StartsWith(this long number, int startsWith) { return StartsWith((int)number, startsWith); }
  • @EZI 我相信这就是协变/逆变的用途...msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx

标签: c# generics extension-methods


【解决方案1】:

数字没有泛型类型约束,但有一组接口约束可供您使用:

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

}

【讨论】:

    【解决方案2】:

    我还没有找到使您的扩展方法更通用的解决方案,但我知道它如何使您的代码更容易。制作一个接受动态参数的普通 FindPlaceNumber-Method

    private static int _FindPlaceNumber(dynamic number)
        {
            var placeNumber = 0;
    
            while (number > 0)
            {
                number = number / 10;
    
                if (number > 0)
                {
                    placeNumber++;
                }
                else
                {
                    placeNumber++;
                    break;
                }
            }
    
            return placeNumber;
        }
    

    然后你可以做三个简短的扩展方法,像这样调用这个方法。

     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);
        }
    

    这是一个快速的选项,可以让您的扩展方法更加“通用”,而无需编写太多代码。动态绑定的缺点是,它比静态类型慢。

    【讨论】:

      猜你喜欢
      • 2016-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-09
      • 1970-01-01
      相关资源
      最近更新 更多