这篇文章主要介绍“C#泛型如何应用”,在日常操作中,相信很多人在C#泛型如何应用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#泛型如何应用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
我们在编写C#程序的时候,经常遇到两个模块的功能非常相似,只是一个是处理int类型,另一个是处理string类型,或者是其他自定义的数据类型,但我们没有其他的解决方案,只能各自写多个方法处理每个数据类型,因为方法的参数类型不同。那么是否有一个办法,在方法中传入通用的数据类型,这样就可以合并代码了。C#泛型应用正是为解决这个问题的。C#泛型应用可以解决什么样的问题呢?我们先看下面的代码,代码中省略了一些内容,但功能是实现一个栈,这个栈只能处理int数据类型:
public class Stack { private int[] m_item; public int pop() {} public void push(int item) {} public Stack(int i) {this.m_item = new int[i]; } }
上面的代码运行得很好,但是,如果我们需要一个栈来保存string类型的数据时呢?或许很多人都会想到把上面的代码copy一份,把int改成string就可以了。当然,这样做,是没问题的,但是如果以后需要long,Node类型的栈该怎么办?继续复制?这里有种折衷的办法,是使用一个通用的数据类型object来实现这个栈:
public class Stack { private object[] m_item; public object pop() {} public void push() {} public Stack(int o){this.m_item = new object [o]} }
虽然这个栈很灵活,可以接收任何数据类型。但全面地说,也不是没有缺陷的,主要表现在:
◆当Stack处理值类型时,会出现装箱,拆箱操作,这将在托管堆上分配和回收大量的变量,若数据量大,则性能损失非常严重。
◆在处理引用类型时,虽然没有装箱和拆箱操作,但将用到数据类型的强制转换操作,增加了处理器的负担。
在数据类型的强制转换上还有更严重的问题,如下:
Node1 x = new Node1(); stack.push(x); Node2 y = (Node2)stack.pop();
上面的代码在编译时是没有问题的,但是由于push了一个Node1类型的数据,但在pop时却要求转换为Node2类型,这将出现程序运行时的类型转换异常,但却逃离了编译器的检查。
针对object类型栈的问题,我们引入泛型,他可以很优雅地解决这些问题。泛型用一个通过的数据类型T来代替object,在类实例化时指定T的类型,运行时(Runtime)自动编译为本地代码,运行效率和代码质量都有很大的提高,并且保证数据类型安全。
C# 泛型应用实例:
下面是使用泛型来重写上面的栈,用一个通用的数据类型T来作为一个占位符,等待在实例化时用一个实际的类型来替换。如下:
public class Stack﹤T﹥ { private T[] m_item; public T pop() {} public void push(T item) {} public Stack(int i) { this.m_item = new T[i]; } }
类的写法不变,只是引入了通用数据类型T就可以适用于任何数据类型,并且类型安全的。这个类的调用方法:
Stack﹤int﹥ a = new Stack﹤int﹥(100); a.push(10); a.push("10"); //这里编译不通过,因为类a只接收int类型的数据 int x = a.pop(); Stack﹤string﹥ b = new Stack﹤string﹥(100); b.push(10); //这里编译不通过,因为类b只接收string类型的数据库 b.push("10"); string y = b.pop();
这个类和object实现的类有截然不同的区别:
他是类型安全的。实例化了int类型的栈,就不能处理string类型的数据,其他数据类型也一样;
无需装箱和拆箱。这个类在实例化时,按照锁传入的数据类型生成本地代码,本地代码数据类型已确定,所以无需装箱和拆箱。
无需数据类型转换。
到此,关于“C#泛型如何应用”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!