C#泛型(Generic)

  • Post author:
  • Post category:其他


泛型(generic)是C#语言2.0和通用语言运行时(CLR)的一个新特性。泛型为.NET框架引入了类型参数(type parameters)的概念。类型参数使得设计类和方法时,不必指定方法有一个或多个具体参数,而是在调用方法的时候再去指定。这意味着使用泛型的类型参数T,写一个方法MyList,客户代码可以这样调用:MyList< int >, MyList< string >,也就是说一个方法就可以满足不同场景的使用。避免了运行时类型转换或装箱操作的代价和风险。



为什么要有泛型,什么时候才用到泛型

以前类型的泛化(generalization)是靠类型与全局基类System.Object的相互转换来实现。比如.NET框架基础类库的ArrayList容器类,就是这种局限的一个例子。ArrayList是一个很方便的容器类,使用中无需更改就可以存储任何引用类型或值类型。

在这里插入图片描述



避免隐式装箱和拆箱

相对于数组来说,这种集合比数组灵活(数组长度固定,数据类型单一),但是这种便利是有代价的,这需要把任何一个加入ArrayList的引用类型或值类型都隐式地向上转换成System.Object(如上图所示)。

如果这些元素是值类型,那么当加入到列表中时,它们必须被装箱;当重新取回它们时,要拆箱。类型转换和装箱、拆箱的操作都降低了性能;在必须迭代(iterate)大容器的情况下,装箱和拆箱的影响可能十分显著。



泛型类

class MyStack<T>
    {
        private T[] stack;
        private int size;
        private int stackPoint;
        public MyStack(int size)
        {
            this.size = size;
            this.stack = new T[size];
            this.stackPoint = -1;
        }
        //入栈
        public void Push(T t)
        {
            if (stackPoint >= size)
            {
                Console.WriteLine("已满");
            }
            else
            {
                stackPoint++;
                this.stack[stackPoint] = t;
            }
        }
        //出栈
        public T Pop()
        {
            T t = this.stack[stackPoint];
            stackPoint--;
            return t;
		}
	}
static void Main(string[] args)
	{
		MyStack<int> myStack = new MyStack<int>(5);
		myStack.Push(1);myStack.Push(2);myStack.Push(3);myStack.Push(4);myStack.Push(5);
		Console.WriteLine(myStack.Pop());
		Console.WriteLine(myStack.Pop());
		Console.WriteLine(myStack.Pop());
		Console.WriteLine(myStack.Pop());
		Console.WriteLine(myStack.Pop());
		Console.ReadLine();
	}



泛型方法

static void Main(string[] args)
        {
            Add<int>(1, 2);
            Add<string>("a", "b");
            Console.Read();
        }
        static void  Add<T>(T a,T b)
        {
            Console.WriteLine(a+"和"+b);
        }



泛型类中的数据约束

class MyGenericClass2<T1, T2, T3>
        where T1:struct//类型必须是值类型
        where T2:class//类型必须是引用类型
        where T3:new()//类型必须有一个无参数构造方法
        //其他类型:基本类型,接口类型
    {
        //产品列表
        public List<T2> ProductList { get; set; } 
        //发行者
        public T3 Publisher { get; set; }
        public MyGenericClass2()
        {
            ProductList = new List<T2>();
            Publisher = new T3();
        }
        public T2 Buy(T1 num)
        {
            //return ProductList[num];//通过下标访问的时候,num不能确定就是int类型
            dynamic a = num;
            return ProductList[a];
        }