何时应在 C# 2.0 及更高版本中使用“对象”?泛型是否替换所有出现的对象
本文关键字:对象 泛型 是否 替换 高版本 版本 何时应 | 更新日期: 2023-09-27 18:35:30
我的同事声称,在.NET 2.0及更高版本中声明变量,返回参数等时,永远不需要使用Object
。
他进一步说,在所有此类情况下,都应使用通用作为替代方案。
这种说法是否有效? 在我的头顶上,我使用 Object
来锁定并发线程......
型在很多情况下胜过object
,但仅限于已知类型的情况下。
有时您仍然不知道类型 - object
,或者在这些情况下,其他一些相关的基本类型是答案。
例如:
object o = Activator.CreateInstance("Some type in an unreferenced assembly");
您将无法强制转换该结果,甚至可能无法在编译时知道类型是什么,因此object
是有效的用法。
你的同事概括得太多了——也许指出他这个问题。泛型很棒,给他那么多,但它们不能"取代"object
.
object
非常适合锁。泛型允许您保持其类型正确。您甚至可以将其限制为接口或基类。你不能用object
做到这一点.
考虑一下:
void DoSomething(object foo)
{
foo.DoFoo();
}
没有任何选角就行不通。但是对于泛型...
void DoSomething<T>(T foo) where T : IHasDoFoo
{
foo.DoFoo();
}
使用 C# 4.0 和 dynamic
,您可以将其推迟到运行时,但我真的没有看到需要。
void DoSomething(dynamic foo)
{
foo.DoFoo();
}
将互操作与 COM 一起使用时,您并不总是有选择...泛型并不能真正满足互操作的问题。
Object
也是lock
最轻量级的选择,正如@Daniel A.怀特在他的回答中提到的。
是的,有有效性。这里已经做了一个很好的细分。
但是,我无法确认是否没有您永远不会使用对象的实例,但我个人不使用它们,甚至在泛型之前,我就避免了装箱/拆箱。
有很多反例,包括你提到的那个,使用对象进行同步。
另一个示例是数据绑定中使用的 DataSource
属性,该属性可以设置为各种不同的对象类型之一。
广泛的反例:System.Collections 命名空间在 .NET 4 中是活的,没有弃用的迹象或警告不要在 MSDN 上使用它。您在那里找到的方法采用并返回对象。
这个问题的内在其实有两个问题:
- 何时应使用类型为"对象"的存储位置
- 何时应使用类型为"对象"的实例
需要保存对该类型实例的引用的任何情况下,必须使用类型 Object
类型的存储位置(因为对此类实例的引用不能保存在任何其他类型中)。 除此之外,它们应该在以下情况下使用:它们将保存对没有单个有用的公共基类型的对象的引用。 这显然适用于许多使用 Reflection 的场景(其中对象的类型可能取决于运行时计算的字符串),但也适用于某些类型的集合,这些集合填充了编译时已知类型的东西。 举一个简单的例子,可以通过让每个节点都是Object
类型,并让它持有一个String
或一个Object[]
来表示一个由int
序列索引的string
的分层集合。 从这样的集合中读出项目会有些笨拙,因为必须检查每个项目并确定它是Object[]
实例还是String
实例,但这种存储方法将非常节省内存,因为唯一的对象实例将是那些保存字符串或数组的对象实例。 人们可以用String
类型的字段和Node[]
类型的字段定义一个Node
类型,甚至可以定义一个具有派生类型的抽象Node
类型StringNode
(包括类型为String
的字段)和ArrayNode
(具有类型为Node[]
的字段),但这种方法会增加用于保存给定数据集的堆对象的数量。
请注意,一般来说,最好设计集合,以便要检索的对象的类型不依赖于推送到集合中的内容(也许对不同类型的"并行集合"使用),但并非所有内容都以这种方式工作语义。
关于类型 Object
的实例,我不确定它们是否可以填补任何角色,而这种角色不会像从Object
继承的称为TokenObject
之类的密封类型那样得到很好的满足。 在许多情况下,拥有一个唯一用途是成为唯一令牌的对象实例很有用。 从概念上讲,最好这样说:
TokenObject myLock = new TokenObject;
比说
对象 myLock = 新对象;
因为前一个声明将明确声明声明的变量永远不会用于保存令牌对象以外的任何内容。 尽管如此,通常的做法是在以下情况下使用类型 Object
的实例:对象唯一重要的是它的引用在程序的整个生命周期中都是唯一的。