当您只存储引用类型时,使用泛型集合是否有任何优势?

时间:2011-03-25 09:53:41

标签: .net boxing generics unboxing

我一直在读一本书并遇到一个声明,即泛型允许程序员在使用例如时,避免需要装箱和拆箱。 Stack

我认为这不完全正确,因为Stack(非通用)只能包含引用类型变量,然后只有转换,没有装箱。

编辑:AFAIK,装箱仅涉及 值对象转换的类型。 这是正确的还是我错过了什么?

2 个答案:

答案 0 :(得分:3)

如果你有Stack<SomeReferenceType>没有(联合国)拳击将会发生,因为参赛永远不需要被装箱。引用是.NET中“正常”方式的工作方式 - object毕竟是引用类型。

修改 您澄清的问题清楚地表明您正在讨论Stack的非泛型变体。你说这个变体不需要box和unbox引用类型是正确的,因为引用类型永远不会被装箱(实际上不能装箱)。如果您将object的子类的实例放入Stack,那么当您将该项目取出并尝试使用该实例的某个方面(这对所有方面都不通用)时,这也是正确的。 object s),那么你需要转换为子类。

注意(对于参考类型)虽然我们在概念上谈到'{1}},但这并不符合实际操作;向上(对象或任何其他超类)是免费的。正是这种情况下,机器需要验证向下转换是否有效。因此,仅使用引用类型实例填充object的非泛型变量是有效的;仅从Stack 转换为更具体的类型时提取开销。

为什么您更喜欢通用集合。

虽然(向下)施法相当便宜,但它并不是免费的。即使对于参考类型,如果您需要再次提取值,期望通用集合略微优于非通用集合。但是,即使您(像往常一样)对几个CPU周期不感兴趣,通用集合也是首选,因为它们可以帮助您更快地发现错误:如果您不小心添加了错误类型的项目非通用列表,在提取并使用该值之前,您不会收到警告,也不会看到错误,这可能会更晚(甚至从不)并且在不同的代码文件中甚至不同的组装。调试这样的错误是一件非常麻烦的事情,特别是如果你的代码有很多层,并且错误不在直接访问集合的层中。

相反,如果您尝试添加不正确类型的值,则通用集合甚至不会编译。即使您需要实现类型不安全的接口并且编译器无法捕获错误,您仍然的优势在于添加项目时会引发Stack到集合(接近bug的根本原因)而不是在提取之后(远离bug的根本原因)。代码中会有bug,你想快速便宜地找到它们,而不是在看似无关的代码中得到奇怪的例外。

实际上,永远使用非泛型集合的唯一原因是与需要使用它们的旧API进行互操作。

答案 1 :(得分:1)

问题是Stack类将您放入其中的对象存储为object。这意味着,每次在堆栈上放置一些东西时,它都会被装入一个对象中,每次你想要使用堆栈中的对象时,你需要再次取消它,以获得正确的类型。