泛型

    通过使用泛型,我们可以极大地提高代码的重用度,同时还可以获得强类型的支持,避免了隐式的装箱、拆箱,在一定程度上提升了应用程序的性能。

    泛型类实例化的理论

    C#泛型类在编译时,先生成中间代码IL,通用类型T只是一个占位符。在实例化类时,根据用户指定的数据类型代替T并由即时编译器(JIT)生成本地代码,这个本地代码中已经使用了实际的数据类型,等同于用实际类型写的类,所以不同的封闭类的本地代码是不一样的。按照这个原理,我们可以这样认为:

    泛型类的不同的封闭类是分别不同的数据类型。

 

    为什么要有泛型

    它可以避免重复代码。如果有几个类或者方法类似,实现功能相同,区别只是类型不一样,如int和string是,这是可以定义一个泛型。

    泛型类就类似于一个模板,可以在需要时为这个模板传入任何我们需要的类型。

 

  由一个例子引入:

  我们在算法中会学到排序,一个很经典的排序为冒泡排序法。将几个乱序的数字用冒泡发排序,我想大多数人会很快的写出来。

  我将例子弄详细一点。新建一张aspx的页面,放一个button和一个label服务器控件,双击button,自动生成响应方法。网页关键代码如下:

1 <asp:Button ID="Button1" runat="server" Text="对1,8,3,7,2排序" onclick="Button1_Click" />

2 <asp:Label ID="Label1" runat="server" Text=""></asp:Label>

  要实现排序,需要现有实现冒泡排序的类,我们新建一个ShortHelper类:

 1 public class ShortHelper {

 2         public void BubbleSort(int[] array)

 3         {

 4             int length = array.Length;

 5             for(int i=0;i<=length-2;i++)

 6                 for (int j = length-1; j >= 1; j--)

 7                 {

 8                     if (array[j] < array[j - 1])

 9                     {

10                         int temp = array[j];

11                         array[j] = array[j - 1];

12                         array[j - 1] = temp;

13                     }

14                 }

15         }

16 }

将相应函数补充完整:

 

protected void Button1_Click(object sender, EventArgs e)

{

            string endsort = "";

            ShortHelper shorter = new ShortHelper();

            int[] array = { 1, 8, 3, 7, 2 };

            shorter.BubbleSort(array);

            foreach (int i in array)

            {

                endsort += i.ToString() + ",";

            }

            int length = endsort.Length - 1;

            endsort = endsort.Substring(0, length);

            Label1.Text = endsort;

}

 

结果如下:

 

 

但是,我现在又想对英文字母或者byte进行排序,怎么办呢,当然直接修改类型是可以的。但是这样会造成代码的不简洁,重用性差。现在我们就引入泛型,泛型其实就是类似于C++中的模版,是一种解决方法的同法,将类型用一个类似于占位符的代替。修改后的类如下:

 1 public class ShortHelper<T> where T : IComparable {

 2         public void BubbleSort(T[] array)

 3         {

 4             int length = array.Length;

 5             for (int i = 0; i <= length - 2; i++)

 6                 for (int j = length - 1; j >= 1; j--)

 7                 {

 8                     if (array[j].CompareTo(array[j - 1]) < 0)//因为object是没有比较大小的方法的,不用IComparable会照成无法比较大小,CompareTo方法用于比较,前一个比后一个小,返回值<0,反之返回>0

 9                     {

10                         T temp = array[j];

11                         array[j] = array[j - 1];

12                         array[j - 1] = temp;

13                     }

14                 }

15         }

16 }

在网页中添加

1 <asp:Button ID="Button2" runat="server" Text="对f,a,s,t,v,b,e排序" onclick="Button2_Click" />

2 <asp:Label ID="Label2" runat="server" Text=""></asp:Label>

相应的相应函数为

 1         protected void Button1_Click(object sender, EventArgs e)

 2         {

 3             string endsort = "";

 4             ShortHelper<int> shorter = new ShortHelper<int>();   //注意此处

 5             int[] array = { 1,8,3,7,2};

 6             shorter.BubbleSort(array);

 7             foreach (int i in array)

 8             {

 9                 endsort += i.ToString() + ",";

10             }

11             int length = endsort.Length - 1;

12             endsort = endsort.Substring(0, length);

13             Label1.Text = endsort;

14         }

15 

16         protected void Button2_Click(object sender, EventArgs e)

17         {

18             string endsort = "";

19             ShortHelper<char> shorter = new ShortHelper<char>();   //注意此处

20             char[] array = { 'f', 'a', 's', 't', 'v', 'b', 'e' };

21             shorter.BubbleSort(array);

22             foreach (char i in array)

23             {

24                 endsort += i + ",";

25             }

26             int length = endsort.Length - 1;

27             endsort = endsort.Substring(0, length);

28             Label2.Text = endsort;

29         }

运行结果为:

当然,泛型的用法不仅仅就这,还有泛型接口,泛型方法等等。

 

    优点:

    1、性能:避免隐式的装箱和拆箱

    如AarryList(在添加数据时装箱,读取时拆箱)和List<T>区别

    2、类型安全:

    泛型的另一个特性是类型安全。与ArrayList类一样,如果使用对象,可以在这个集合中添加任意类型。下面的例子在ArrayList类型的集合中添加一个整数、一个字符串和一个MyClass类型的对象:

1 ArrayList list = new ArrayList();

2 list.Add(44);

3 list.Add("mystring");

4 list.Add(new MyClass());

  如果这个集合使用下面的foreach语句迭代,而该foreach语句使用整数元素来迭代,编译器就会编译这段代码。但并不是集合中的所有元素都可以转换为int,所以会出现一个运行异常:

1 foreach (int i in list)

2 {

3     Console.WriteLine(i);

4 }

  错误应尽早发现。在泛型类List<T>中,泛型类型T定义了允许使用的类型。有了List<int>的定义,就只能把整数类型添加到集合中。编译器不会编译这段代码,因为Add()方法的参数无效:

1 List<int> list = new List<int>();

2 list.Add(44);

3 list.Add("mystring");   // compile time error

4 list.Add(new MyClass());   // compile time error

    3、二进制代码的重用:

    泛型允许更好地重用二进制代码。泛型类可以定义一次,用许多不同的类型实例。

   类型参数约束

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

    除了可以约束类型参数T 实现某个接口以外,还可以约束T 是一个结构、T 是一个类、T 拥有构造函数、T 继承自某个基类等。

    泛型方法

    在泛型方法中,泛型类型用方法声明来定义。

 

1 void Swap<T>(ref T x, ref T y)

2 {

3   T temp;

4   temp = x;

5   x = y;

6   y = temp;

7 }

 

把泛型类型赋予方法调用,就可以调用泛型方法:

1 int i = 4;

2 int j = 5;

3 Swap<int>(ref i, ref j);

但是,因为C#编译器会通过调用Swap方法来获取参数的类型,所以不需要把泛型类型赋予方法调用。泛型方法可以像非泛型方法那样调用:

1 int i = 4;

2 int j = 5;

3 Swap(ref i, ref j);

当一般方法与泛型方法具有相同的签名时,会覆盖泛型方法。

    泛型类的特性

    1、默认值:不能把null赋予泛型类型。原因是泛型类型也可以实例化为值类型,而null只能用于引用类型。为了解决这个问题,可以使用default关键字。通过default关键字,将null赋予引用类型,将0赋予值类型。

        T doc = default(T);

  2、约束:如果泛型类需要调用泛型类型上的方法,就必须添加约束。

 

约    束

说    明

where T : struct

使用结构约束,类型T必须是值类型

where T : class

类约束指定,类型T必须是引用类型

where T : IFoo

指定类型T必须执行接口IFoo

where T : Foo

指定类型T必须派生于基类Foo

where T : new()

这是一个构造函数约束,指定类型T必须有一个默认构造函数

where T : U

这个约束也可以指定,类型T1派生于泛型类型T2。该约束也称为裸类型约束

 

  3、继承:泛型类型可以执行泛型接口,也可以派生于一个类。泛型类可以派生于泛型基类:

1 public class Base<T>

2 {

3 }

4 public class Derived<T> : Base<T>{}

  4、静态成员:泛型类的静态成员需要特别关注。泛型类的静态成员只能在类的一个实例中共享。

总结:

  泛型。通过泛型类可以创建独立于类型的类,泛型方法是独立于类型的方法。增加代码的重用性。接口、结构和委托也可以用泛型的方式创建。泛型引入了一种新的编程方式。

 

参考资料:http://www.cnblogs.com/JimmyZhang/archive/2008/12/17/1356727.html,《C#高级编程第六版》

 



你可能感兴趣的:(泛型)