Object
我的同事声称在 .NET 2.0 及更高版本中声明变量、返回参数等时永远不需要使用。
他进一步说,在所有这些情况下,都应该使用 Generic 作为替代方案。
这种说法是否有效?在我的脑海中,我用它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
也是 a 最轻量级的选项lock
,正如@Daniel A. White在他的回答中提到的那样。
是的,有有效性。这里已经进行了很好的细分。
但是,我无法确认是否没有您永远不会使用对象的实例,但我个人不使用它们,甚至在泛型之前我避免装箱/拆箱。
有很多反例,包括你提到的那个,使用对象进行同步。
另一个例子是DataSource
数据绑定中使用的属性,它可以设置为多种不同的对象类型之一。
广泛的反例:System.Collections 命名空间在 .NET 4 中仍然存在并且运行良好,没有任何弃用迹象或警告不要在 MSDN 上使用它。您在那里找到的方法获取并返回对象。
问题中固有的实际上是两个问题:
类型的存储位置Object
显然必须在任何需要保存对该类型实例的引用的情况下使用(因为对此类实例的引用不能保存在任何其他类型中)。除此之外,它们应该在它们持有对没有单一有用的公共基类型的对象的引用的情况下使用。这在许多使用反射的场景中显然是正确的(其中对象的类型可能取决于在运行时计算的字符串),但也可以应用于某些类型的集合,其中填充了在编译时类型已知的东西。string
作为一个简单的例子,一个可以表示一个由序列索引的分层集合,int
通过让每个节点的类型Object
为String
Object[]
. 从这样的集合中读取项目会有些笨拙,因为必须检查每个项目并确定它是否是Object[]
or的实例String
,但是这种存储方法将非常节省内存,因为唯一的对象实例是那些保存字符串或数组的。可以使用Node
type 字段和 type 字段定义String
类型Node[]
,甚至可以Node
使用派生类型StringNode
(包括 type 字段String
)和ArrayNode
(带有type 字段)定义抽象类型,Node[]
但这种方法会增加使用的堆对象的数量保存一组给定的数据。
请注意,通常最好设计集合,以便要检索的对象的类型不取决于被推入集合中的内容(可能对不同的类型使用“并行集合”),但并非一切都以语义方式进行。
关于 type 的实例Object
,我不确定他们可以扮演的任何角色都不能被称为类似TokenObject
which 继承自的密封类型所满足Object
。在许多情况下,拥有一个唯一目的是成为唯一标记的对象实例很有用。从概念上讲,这样说可能会更好:
令牌对象 myLock = 新令牌对象;
不如说
对象 myLock = 新对象;
因为前一个声明会清楚地表明,声明的变量永远不会被用来保存除了令牌对象之外的任何东西。尽管如此,通常的做法是Object
在对象唯一重要的是它的引用在程序的整个生命周期中将是唯一的情况下使用类型的实例。