C#泛型(二)

<1>.泛型方法

以前文章说到用一个泛型类 SortHelper 来做一个冒泡排序的处理,下面回顾一下之前的代码:

 public class SortHelper<T> where T:IComparable
    {
        public void BubbleSort(T[] arr)
        {
            int length = arr.Length;
            for (int i = 0; i < length-1; i++)
            {
                for (int j = 0; j < length-1-i; j++)
                {
                    if (arr[j].CompareTo(arr[j+1])>0)
                    {
                        T temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                }
            }
        }
    }

 这里我们为了调用 BubbleSort,而将参数T传递给类 SortHelper,假如 SortHelper 类中,除了 BubbleSort 方法之外,还有其他的没有使用到参数T的方法 比如:

 public class SortHelper<T> where T:IComparable
    {
        public void BubbleSort(T[] arr)
        {
                //省略
        }
        
        public void OtherMethod1()
        {
                //省略
        }
        //此处省略N个OtherMethod
    }

这里有 N 个 OtherMethod方法。

测试-调用 OtherMethod1:

static void Main(string[] args)
        {
            SortHelper<int> UserOtherMethod = new SortHelper<int>();
            UserOtherMethod.OtherMethod1();
        }

 在实例化 UserOtherMethod 对象时 必须给 SortHelper 传一个类型参数 这里是 int  。显然这中情况下,我们仅仅是为了 BubbleSort 方法正常使用而定义泛型类,从而强迫其他使用 SortHelper 类其它方法

实例传递一个参数,很明显这是没必要的,于是这个时候 ’泛型方法‘ 就出现了 ,修改代码如下:

 public class SortHelper2
    {
        public void BubbleSort<T>(T[] arr) where T:IComparable
        {
            int length = arr.Length;
            for (int i = 0; i < length - 1; i++)
            {
                for (int j = 0; j < length - 1 - i; j++)
                {
                    if (arr[j].CompareTo(arr[j + 1]) > 0)
                    {
                        T temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                }
            }
        }
    }

总结:

泛型方法和普通方法没多大区别,仅仅在方法名后面加了“<T>”, 接着是括号里面的参数,最后是限定语句。

上述的这种情况,我们通过使用泛型方法,就可以避免每次使用泛型类传参了。

<2>.泛型接口

自己写了一个 “cat” 类,并调用了一个接口“IComparable” 代码如下:

 public class cat:IComparable
    {
        public string name;
        public int price;

        public int CompareTo(object obj)
     {
      cat catT = (cat)obj;
      return this.price.CompareTo(catT.price);
     }
     public cat(string name, int price)
        {
            this.price = price;
            this.name = name;
        }
    }

 这里粉红色标记的部分我们实现了 “IComparable” 接口的 “CompareTo” 方法 这里没有进行装箱和拆箱。

因为cat是引用类型,而且“ return this.price.CompareTo(catT.price) ”这里调用的是 price (int型) 的 ComparaTo 方法,右键对int转到定义查看代码。

这里可以清楚的看到int类型实现了 IComparable 与 IComparable<int> 这两个接口,也就是说它分别实现了这两个接口的 ComparaTo() 方法,那这里又是调用那个接口的 ComparaTo() 方法呢?

实际上这里传过来的参数是int类型,那么优先调用的是 ComparaTo(int value) 方法,这样就避免了不必要的装箱拆箱过程了。

上图中是.NET 中 int 类型实现 IComparable 接口的 ComparaTo(object value) 方法,不难看出“红箭头”标记部分是执行装箱拆箱操作的过程。

下图是 int类型实现泛型版本的 IComparable<int> 的 ComparaTo(int value) 方法,如果对2种方法进行大量重复操作,不难发现使用泛型接口实现的方法性能比较好。

总结:

程序设计中应该尽量避免装箱和拆箱操作,为了避免多次装箱拆箱造成的性能影响 ,通过上面的例子我们可以知道使用泛型接口可以有效的避免这个问题:使用IComparable<T> 而不使用 IComparable,这样可以避免值类型的装箱和取消装箱操作。

原文地址:https://www.cnblogs.com/sunliyuan/p/5918642.html