C# 中的泛型

C# 中的泛型允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。换句话说,在声明类或方法的时候由于不知道用户要传入什么样类型的参数,所以在传入类型的地方“挖一个坑(“<T>”)",使用它的时候我们再用具体数据类型填上。

1、泛型类:

using System;  
2.using System.Collections.Generic;  
3.using System.Linq;  
4.using System.Text;  
5.  
6.namespace Example  
7.{  
8.    class Data<T> //泛型类  
9.    {  
10.        public T[] n_data; //泛型变量  
11.       public Data(int size) //构造方法,new的时候调用构造方法开辟空间  
12.        {   
13.          n_data = new T[size];    
14.        }  
15.        //输入  
16.       public void setdata(int index,T value)  
17.       {  
18.           n_data[index] = value;  
19.       }  
20.        //输出  
21.       public T getdata(int x)  
22.       {   
23.          return n_data[x];  
24.       }  
25.    }  
26.    class Program  
27.    {  
28.        static void Main(string[] args)  
29.        {  
30.            Data<int> data = new Data<int>(5);  
31.            data.n_data[2] = 2;  
32.           Console.WriteLine(data.n_data[2]);  
33.        }  
34.    }  
35.}  

2、泛型方法:

using System;  
2.using System.Collections.Generic;  
3.using System.Linq;  
4.using System.Text;  
5.  
6.namespace Example  
7.{  
8.    class Data<T> //泛型类  
9.    {  
10.        public T[] n_data; //泛型变量  
11.       public Data(int size) //构造方法,new的时候调用构造方法开辟空间  
12.        {   
13.          n_data = new T[size];    
14.        }  
15.        //输入  
16.       public void setdata(int index,T value)  
17.       {  
18.           n_data[index] = value;  
19.       }  
20.        //输出  
21.       public T getdata(int x)  
22.       {   
23.          return n_data[x];  
24.       }  
25.    }  
26.    class Program  
27.    {  
28.        static void Main(string[] args)  
29.        {  
30.            Data<int> data = new Data<int>(5);  
31.            data.n_data[2] = 2;  
32.           Console.WriteLine(data.n_data[2]);  
33.        }  
34.    }  
35.}  

泛型约束方法在form 窗口编程上的应用

private T OpenUniqueMDIChildWindow<T>(Form mdiParent) where T : Form, new()
        {
            foreach (Form subForm in mdiParent.MdiChildren)
            {
                if (!subForm.GetType().Equals(typeof(T)))
                {
                    subForm.Close();
                }
                else
                {
                    subForm.Activate();
                    return subForm as T;
                }
            }
            T newForm = new T();
            newForm.MdiParent = mdiParent;
            //newForm.FormBorderStyle = FormBorderStyle.None;
            //newForm.WindowState = FormWindowState.Maximized;
            //newForm.MaximizeBox = false;
            //newForm.MinimizeBox = false;

            newForm.StartPosition = FormStartPosition.CenterScreen;
            newForm.Show();
            return newForm;
        }
//
private void btsmiBuildInfo_Click(object sender, EventArgs e)
        {
            OpenUniqueMDIChildWindow<BuildInfo>(this);
        }

        private void dtsmiDormInfo_Click(object sender, EventArgs e)
        {
            OpenUniqueMDIChildWindow<DormInfo>(this);
        }

3、泛型委托

using System;  
2.using System.Collections.Generic;  
3.using System.Linq;  
4.using System.Text;  
5.  
6.namespace Example  
7.{  
8.    public delegate void MyDelegate<T>();//泛型委托  
9.    class Data<T>  
10.    {  
11.        private T a;  
12.        private T b;  
13.        public void setvalue(T x, T y)  
14.        {  
15.            a = x;  
16.            b = y;  
17.        }  
18.        //swap方法,ref是按地址传递  
19.        public void swap()  
20.        {  
21.            T temp;  
22.            temp = a;  
23.            a = b;  
24.            b = temp;  
25.        }  
26.        public void printvalue()  
27.        {  
28.            Console.WriteLine(a + "	" + b);  
29.  
30.        }  
31.  }  
32.      class program  
33.       {   
34.         static void Main(string[] args)  
35.          {  
36.            Data<string> data = new Data<string>();  
37.            data.setvalue("HC","666");  
38.            MyDelegate<string> my = new MyDelegate<string>(data.swap);  
39.            my += data.printvalue;  
40.            my();  //结果 666  HC        
41.           }  
42.          
43.       }  
44.        
45.   }  

泛型类中数据类型的约束 程序员在编写泛型类时,总是会对通用数据类型T进行有意或无意地有假想,也就是说这个T一般来说是不能适应所有类型,但怎样限制调用者传入的数据类型呢?这就需要对传入的数据类型进行约束,约束的方式是指定T的祖先,即继承的接口或类。因为C#的单根继承性,所以约束可以有多个接口,但最多只能有一个类,并且类必须在接口之前。这时就用到了C#2.0的新增关键字:

public class Node<T, V> where T : Stack, IComparable

        where V: Stack

    {...}

以上的泛型类的约束表明,T必须是从Stack和IComparable继承,V必须是Stack或从Stack继承,否则将无法通过编译器的类型检查,编译失败。

通用类型T没有特指,但因为C#中所有的类都是从object继承来,所以他在类Node的编写中只能调用object类的方法,这给程序的编写造成了困难。比如你的类设计只需要支持两种数据类型int和string,并且在类中需要对T类型的变量比较大小,但这些却无法实现,因为object是没有比较大小的方法的。 了解决这个问题,只需对T进行IComparable约束,这时在类Node里就可以对T的实例执行CompareTo方法了。这个问题可以扩展到其他用户自定义的数据类型。

如果在类Node里需要对T重新进行实例化该怎么办呢?因为类Node中不知道类T到底有哪些构造函数。为了解决这个问题,需要用到new约束:

public class Node<T, V> where T : Stack, new()

        where V: IComparable

需要注意的是,new约束只能是无参数的,所以也要求相应的类Stack必须有一个无参构造函数,否则编译失败。

C#中数据类型有两大类:引用类型和值类型。引用类型如所有的类,值类型一般是语言的最基本类型,如int, long, struct等,在泛型的约束中,我们也可以大范围地限制类型T必须是引用类型或必须是值类型,分别对应的关键字是class和struct:

public class Node<T, V> where T : class

        where V: struct

泛型方法 泛型不仅能作用在类上,也可单独用在类的方法上,他可根据方法参数的类型自动适应各种参数,这样的方法叫泛型方法。看下面的类:

public class Stack2

    {

        public void Push<T>(Stack<T> s, params T[] p)

        {

            foreach (T t in p)

            {

                s.Push(t);

            }

        }

}

原来的类Stack一次只能Push一个数据,这个类Stack2扩展了Stack的功能(当然也可以直接写在Stack中),他可以一次把多个数据压入Stack中。其中Push是一个泛型方法,这个方法的调用示例如下:

Stack<int> x = new Stack<int>(100);

    Stack2 x2 = new Stack2();

    x2.Push(x, 1, 2, 3, 4, 6);

    string s = "";

    for (int i = 0; i < 5; i++)

    {

        s += x.Pop().ToString();

    }    //至此,s的值为64321


 

原文地址:https://www.cnblogs.com/wenjie0904/p/7912878.html