C#中怎么实现泛型处理,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
C#泛型处理的问题陈述
考虑一种普通的、提供传统 Push() 和 Pop() 方法的数据结构(例如,堆栈)。在开发通用堆栈时,您可能愿意使用它来存储各种类型的实例。在 C# 1.1 下,您必须使用基于 Object 的堆栈,这意味着,在该堆栈中使用的内部数据类型是难以归类的 Object,并且堆栈方法与 Object 交互:
public class Stack { object[] m_Items; public void Push(object item) {...} public object Pop() {...} }
C#泛型处理代码块
显示基于 Object 的堆栈的完整实现。因为 Object 是规范的 .NET 基类型,所以您可以使用基于 Object 的堆栈来保持任何类型的项(例如,整数):
Stack stack = new Stack(); stack.Push(1); stack.Push(2); int number = (int)stack.Pop();
基于 Object 的堆栈
public class Stack { readonly int m_Size; int m_StackPointer = 0; object[] m_Items; public Stack():this(100) {} public Stack(int size) { m_Size = size; m_Items = new object[m_Size]; } public void Push(object item) { if(m_StackPointer >= m_Size) throw new StackOverflowException(); m_Items[m_StackPointer] = item; m_StackPointer++; } public object Pop() { m_StackPointer--; if(m_StackPointer >= 0) { return m_Items[m_StackPointer]; } else { m_StackPointer = 0; throw new InvalidOperationException( "Cannot pop an empty stack"); } } }
但是,基于 Object 的解决方案存在两个问题。***个问题是性能。在使用值类型时,必须将它们装箱以便推送和存储它们,并且在将值类型弹出堆栈时将其取消装箱。装箱和取消装箱都会根据它们自己的权限造成重大的性能损失,但是它还会增加托管堆上的压力,导致更多的垃圾收集工作,而这对于性能而言也不太好。即使是在使用引用类型而不是值类型时,仍然存在性能损失,这是因为必须从 Object 向您要与之交互的实际类型进行强制类型转换,从而造成强制类型转换开销:
Stack stack = new Stack(); stack.Push("1"); string number = (string)stack.Pop();
基于 Object 的解决方案的第二个问题(通常更为严重)是类型安全。因为编译器允许在任何类型和 Object 之间进行强制类型转换,所以您将丢失编译时类型安全。例如,以下代码可以正确编译,但是在运行时将引发无效强制类型转换异常:
Stack stack = new Stack(); stack.Push(1); //This compiles, but is not type safe, and will throw an exception: string number = (string)stack.Pop();
您可以通过提供类型特定的(因而是类型安全的)高性能堆栈来克服上述两个问题。对于整型,可以实现并使用 IntStack:
public class IntStack { int[] m_Items; public void Push(int item){...} public int Pop(){...} } IntStack stack = new IntStack(); stack.Push(1); int number = stack.Pop();
对于字符串,可以实现 StringStack:
public class StringStack { string[] m_Items; public void Push(string item){...} public string Pop(){...} } StringStack stack = new StringStack(); stack.Push("1"); string number = stack.Pop();
C#泛型处理问题的出现必然性:
遗憾的是,以这种方式解决性能和类型安全问题,会引起第三个同样严重的问题 — 影响工作效率。编写类型特定的数据结构是一项乏味的、重复性的且易于出错的任务。在修复该数据结构中的缺陷时,您不能只在一个位置修复该缺陷,而必须在实质上是同一数据结构的类型特定的副本所出现的每个位置进行修复。此外,没有办法预知未知的或尚未定义的将来类型的使用情况,因此还必须保持基于 Object 的数据结构。结果,大多数 C# 1.1 开发人员发现类型特定的数据结构不实用,并且选择使用基于 Object 的数据结构,尽管它们存在缺点。
看完上述内容,你们掌握C#中怎么实现泛型处理的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。