C#泛型理解

泛型不是简单的语法糖,还有赖于.NET框架升级支持。
摘要由CSDN通过智能技术生成

C#泛型理解

“泛型是2.0及以上版本C#编程语言和CLR提供的一种特殊机制,他支持另一种形式的代码重用,即’算法重用’ ”。(From《CLR via C#》)
泛型实现了构造泛型类、方法、接口等未指定数据类型,到使用时才指定,它完美体现了设计思想——延迟声明:延迟一切可以延迟的。
泛型不是简单的语法糖,它的实现有赖于.NET框架升级支持。

命名空间:using System.Collections.Generic

一、泛型应用场景

        static void Main(string[] args)
        {
            Printf("你好~");
            Printf(1);
            Printf(false);
            Console.ReadKey();
        }

        private static void Printf(string input)
        {
            Console.WriteLine("输入为:{0},{1}" ,input,input.GetType());
        }

        private static void Printf(int input)
        {
            Console.WriteLine("输入为:{0},{1}", input, input.GetType());
        }

        private static void Printf(bool input)
        {
            Console.WriteLine("输入为:{0},{1}", input, input.GetType());
        }

可以看出,以上三个方法的区别只在于传入的参数类型不一样,方法内实现的功能是一样的,这个时候我们有两种方法,一是将传入参数类型声明为object,另一种是使用泛型。
为什么不建议使用object?

        static void Main(string[] args)
        {
            //正常输出
            object input = "你好~";
            Printf(input);

            //强制转换,编译时不报错,但运行时出错
            int nStr = (int)input;
            Printf(nStr);
        }

        private static void Printf(object input)
        {
            Console.WriteLine("输入为:{0},{1}" ,input,input.GetType());
        }

由此可以看到使用object需要强制转换,强制转换的装箱拆箱会造成很多性能损耗,除了性能外,object不能保证类型安全,强制转换就是告诉编译器,这样的转换是安全的,到运行时转换失败,就会造成数据丢失。

二、泛型的优势

1.源代码保护;
2.类型安全;
3、代码更清晰、易维护性能
4.性能更佳。

下面代码展示了一下泛型List和非泛型ArrayList的性能差异。

using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            const Int32 count = 100000000;
            using (new MyTimer("List<Int32>"))
            {
                List<Int32> l = new List<int>();
                for (Int32 i = 0; i < count; i++)
                {
                    l.Add(i);  //不用装箱
                    Int32 n = l[i];   //不用拆箱
                }
                l = null;
            }

            using (new MyTimer("ArrayList"))
            {
                ArrayList array = new ArrayList();
                for (Int32 i = 0; i < count; i++)
                {
                    array.Add(i); //发生装箱
                    Int32 n = (Int32)array[i]; //发生拆箱
                }
            }
            Console.ReadKey();
        }
    }

    /// <summary>
    /// 用于计算性能用时的自定义类
    /// </summary>
    internal sealed class MyTimer : IDisposable
    {
        private Stopwatch stopwatch;

        private string text;
        private Int32 collectionCount;

        public MyTimer(string _text)
        {
            PrepareForAction();
            text = _text;
            collectionCount = GC.CollectionCount(0);

            stopwatch = Stopwatch.StartNew();
        }

        public void Dispose()
        {
            Console.WriteLine("{0} (GCs={1,3}) {2}", stopwatch.Elapsed, GC.CollectionCount(0) - collectionCount, text);
        }

        /// <summary>
        /// 进行垃圾回收
        /// </summary>
        private static void PrepareForAction()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
        }
    }
}

运行结果
从运行结果可以看出,操作值类型时,泛型List算法比非泛型ArrayList快多了,0.96和7.6秒的差异,此外,操作非泛型造成大量装箱拆箱,最后要进行388次垃圾回收,而泛型算法只需要8次。
不过,对于引用类型数据,差异不明显,垃圾回收次数和时间都差不多(你们可以自测一下)

三、泛型的几种应用
泛型的应用有泛型集合类,泛型接口,泛型方法。

/// <summary>
        /// 泛型方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static void Show<T>(T tParameter)
        {
            Console.WriteLine("This is parameter={0},type={1}",tParameter.GetType().Name, tParameter.ToString());
        }
/// <summary>
    /// 泛型类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class GenericClass<T>
    {
        public T _T;
    }
/// <summary>
    /// 泛型接口
    /// </summary>
    public interface IGenericInterface<T>
    {
        //泛型类型的返回值
        T GetT(T t);
    }
public delegate void SayHi<T>(T t);//泛型委托

虽然能自定义泛型委托,但最好是使用框架自带的委托。

四、泛型约束
泛型约束格式:使用where关键字
泛型约束的意义:保证传递的类型参数符合一定的条件,能在编译阶段对传入的参数进行验证

类型约束格式示例
接口约束T:<接口名称>public class MyGenericClass where T:IComparable { }
基类约束T:<基类名>class MyClassy<T, U> where T : class
引用约束T:classpublic class BaseAccess where T : class{}
值约束T:structpublic class MyClass9 where T : struct { }
构造函数约束T:new()public class MyGenericClass where T: IComparable, new(){T item = new T(); }
裸类型约束T:Uclass List{void Add(List items) where U : T { }}

泛型约束注意事项:
1.多个约束
不可能同时添加struct和class约束
不可能添加多个基类约束
约束之间是 and 关系,不能添加or关系的约束
构造函数约束必须最后
构造函数约束只能指明无参构造器
约束不会继承

2.多个参数
对于一种表示“键值对”关系的泛型类KeyValue<TKey,TValue>,该类具有两个泛型参数TKey,TValue,要为其都添加约束。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值