List<T>和List<object>之间的区别是什么?

10

由于所有东西都继承自object,那么List<T>List<object>有什么区别? 有什么优缺点?

6个回答

14
如果你将一个 int 插入到 List<object> 中,它会被装箱。如果你将它插入到 List<int> 中,它不会被装箱(这对于任何值类型都是如此,用该类型的名称替换 int 即可)。同样地,从 List<object> 检索值时,会发生拆箱,但从 List<int> 中检索时不会发生。 List<T> 是强类型的,List<object> 不是(因此你会失去编译时的安全性,并可能遇到运行时错误)。

12
如果你有一个 List<T>,那么你可以确保在实例化对象后,该列表只包含 T 类型的实例。但是在 List<object> 中,你可以放置任何类型的对象。
泛型是一种好的编写可重用代码且在编译时具有强类型的方式。

那么,如果列表可以包含不同类型的元素,使用对象会更好吗? - Xaisoft
1
顺便说一句,回答得很好。我没有考虑到使用List<T>相对于List<object>的类型安全性。 - Xaisoft

5
如果你使用 List<object>,你将不会有任何项目类型,并且需要进行强制转换。此外,这种方法很危险,因为你可以放入任何东西到列表中,而不知道确切的返回值是什么。

谢谢你修复括号,约翰。我正准备去做那个。 - Joshua Marble
“...项目类型...”是指在进行强制转换之前,我无法访问属性或方法吗? - Xaisoft
你正在添加正确类型的项到集合中,这需要编译时支持。然而,最明显的缺点是无法在没有强制转换的情况下与对象交互。 - Joshua Marble

3

List以通用类型作为模板参数。因此,如果您执行以下操作,您将真正拥有一辆汽车列表:

List<car> list = new List<car>();

鉴于:

List<object> objlist = new List<object>();

可以保存任何类型的引用。但问题在于,这些引用被降级为对象,直到你将它们重新转换为正确的对象后才能使用其成员和函数。例如,如果你在objlist中保存了汽车,你需要执行以下操作:

((car)objlist[0]).GetMaker();

调用汽车 GetMaker 函数,而使用列表可以这样做:
list[0].GetMaker();

这里假设您的列表中至少有一辆车/对象。

不错的例子。帮助我更好地理解了。 - Xaisoft

1

你可以将 T 视为 List 的类型约束。因此,如果你说

class Vehicle {} 
class Car : Vehicle {}
class Boat : Vehicle {}
class SpeedBoat : Boat {}
List<Boat> listOfBoats 

列表只能包含一种类型的船和它的子类,而不能包含其他任何车辆。如果你将其设置为对象,那么列表基本上可以包含任何引用类型。
请注意,如果你想从该集合中获取所有速度艇,可以使用方便的扩展方法OfType:
//Returns IEnumerable<SpeedBoat>, casting is done for you
var speedBoats = listOfBoats.OfType<SpeedBoat>(); 

List<Vehicle> 可以让我使用 Car 和 Boat,对吗?由于 SpeedBoat 继承自 Boat,而 Boat 又继承自 Vehicle,那么我只需要使用 List<SpeedBoat>,还是必须使用 OfType 扩展? - Xaisoft
是的,List(of Vehicles)可以包含Car、Boat、Speedboat或任何Vehicle的子类。List<SpeedBoat>不允许例如.Add(new Boat())。如果您想从已填充的List<Vehicle>中获取List<SpeedBoat>,则可以说List<SpeedBoat> sbs = vehicles.OfType<SpeedBoat>()。 - edvaldig

0
这个问题有点令人困惑,但我认为 jsmarble 已经提到了一个主要的点:你必须将所有东西都转换为所需的类型。这是低效的,特别是对于值类型而言,在不必进行装箱和拆箱的情况下,List<T>可以很好地处理它们。
另外,你会牺牲类型安全性,这可能会导致运行时错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接